Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Segment Fault after producing debug information

qu__xing
Beginner
783 Views

Hi,

    When compiling the following program without the -g parameter, the run result is -1. After the -g parameter is added, the run result is reported as a Segment Fault. Perhaps intelc has some optimizations by default. Is this a correct behavior for intel c complier?

 

TestCase:

#include<stdio.h>

#include<string.h>

int has_8bit(int i)

{

    return strcmp(i, "none");

}

int main(void){

    int NISLParameter0 = -4569;

    int NISLParameter1 = has_8bit(NISLParameter0);

    printf("%d",NISLParameter1);

    return 0;

}

 

The OS is:

Linux version 4.15.0-65-generic

 

Compiler Version:

icc (ICC) 19.0.4.243 20190416

0 Kudos
12 Replies
Viet_H_Intel
Moderator
783 Views

Does the test case NOT give SegFault with GCC?

0 Kudos
Vladimir_P_1234567890
783 Views

Hello, this code can't be compiled

prog.cpp:6:19: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
     return strcmp(i, "none");
                   ^
In file included from prog.cpp:1:
/usr/include/string.h:136:32: note:   initializing argument 1 of ‘int strcmp(const char*, const char*)’
 extern int strcmp (const char *__s1, const char *__s2)
                    ~~~~~~~~~~~~^~~~

 

0 Kudos
qu__xing
Beginner
783 Views

Viet Hoang (Intel) wrote:

Does the test case NOT give SegFault with GCC?

Hello Viet:

     In GCC, it gives SegFault with or without -g/-O0 options. But in intelc, the behavior is inconsistent with or without -g/-O0 options. When there are no options at compile time, just like "icc testcase.c -o testcase", the run result is -1. After adding options -g/-O0 at compile time, just like "icc -g testcase.c -o testcase" the run result is SegFault. So I wonder if this is an optimization problem for the compiler icc. Sorry if I'm misunderstanding something.

0 Kudos
qu__xing
Beginner
783 Views

Vladimir Polin (Intel) wrote:

Hello, this code can't be compiled

prog.cpp:6:19: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
     return strcmp(i, "none");
                   ^
In file included from prog.cpp:1:
/usr/include/string.h:136:32: note:   initializing argument 1 of ‘int strcmp(const char*, const char*)’
 extern int strcmp (const char *__s1, const char *__s2)
                    ~~~~~~~~~~~~^~~~

 

Hello Vladimir:

      It seems that you compiled it with the icpc compiler. But the problem is with the c compiler ICC. ICC prints a warning but eventually compiles it successfully.

0 Kudos
Viet_H_Intel
Moderator
783 Views

But first, you need to fix the call to strcmp(i, "none"); 

0 Kudos
qu__xing
Beginner
783 Views

Viet Hoang (Intel) wrote:

But first, you need to fix the call to strcmp(i, "none"); 

        ICC can certainly run as expected when the first parameter is fixed to be string instead of int. But, I think if I pass an unexpected type int to the first parameter of the strcmp(const char* s1, const char* s2), maybe it should give the SegFault instead of -1 because it doesn't make sense to compare int and string using strcmp.

0 Kudos
Viet_H_Intel
Moderator
783 Views

I got your point. our nextgen compiler (19.1) gives a SegFault.

$ icc t.c -w -qnextgen -V&&./a.out

Intel(R) C Compiler for applications running on Intel(R) 64, Version 2021.1 NextGen Build 20191121
Segmentation fault (core dumped)

0 Kudos
Vladimir_P_1234567890
783 Views

qu, xing wrote:

        ICC can certainly run as expected when the first parameter is fixed to be string instead of int. But, I think if I pass an unexpected type int to the first parameter of the strcmp(const char* s1, const char* s2), maybe it should give the SegFault instead of -1 because it doesn't make sense to compare int and string using strcmp.

In C world it is called "undefined behaviour". You did not pass "int" you passed HEX(-4569) address of const char in your application. If your pointer (-4569) points to readable section it will compare the garbage to your "none" string. If this is non-readable section it segfaults. it is not only compiler, it is up to LD linker where to set sections. It looks for your release version there is readable "0" in the memory at HEX(-4569) address so you get -1.

In general - "garbage in -> garbage out".

Vladimir 

0 Kudos
qu__xing
Beginner
783 Views

Viet Hoang (Intel) wrote:

I got your point. our nextgen compiler (19.1) gives a SegFault.

$ icc t.c -w -qnextgen -V&&./a.out

Intel(R) C Compiler for applications running on Intel(R) 64, Version 2021.1 NextGen Build 20191121
Segmentation fault (core dumped)

That's good! Thanks for your reply.

0 Kudos
qu__xing
Beginner
783 Views

Vladimir Polin (Intel) wrote:

Quote:

qu, xing wrote:

 

        ICC can certainly run as expected when the first parameter is fixed to be string instead of int. But, I think if I pass an unexpected type int to the first parameter of the strcmp(const char* s1, const char* s2), maybe it should give the SegFault instead of -1 because it doesn't make sense to compare int and string using strcmp.

 

 

In C world it is called "undefined behaviour". You did not pass "int" you passed HEX(-4569) address of const char in your application. If your pointer (-4569) points to readable section it will compare the garbage to your "none" string. If this is non-readable section it segfaults. it is not only compiler, it is up to LD linker where to set sections. It looks for your release version there is readable "0" in the memory at HEX(-4569) address so you get -1.

In general - "garbage in -> garbage out".

Vladimir 

Thank you Vladimir for your detailed explanation! And how do you know the pointer(-4569) points to readable "0" instead of others?

0 Kudos
jimdempseyatthecove
Honored Contributor III
782 Views

The arbitrary value of the integer could resolve to a pointer anywhere within the range of the integer. The resultant address may or may not be an address that is or can be mapped to your process virtual address space. If not mapped, you get a segfault.If mapped, or becomes mapped, the strcmp has something to work with. When the assumed string at arbitrary virtual address is scanned, there is a potential that the partially matching scan crosses into a virtual address that is not mapped and not mapable (or is marked execute only), and in which case you get a segfault. However, should the attempted match succeed (unlikely) or fail (see string termination 0), then the appropriate result is returned. "garbage in -> garbage out".

Please use error and warning checking for arguments on function calls, and correct the errors in your program. Do not expect undefined behavior to produce expected and/or same results.

Jim Dempsey

0 Kudos
Vladimir_P_1234567890
782 Views

qu, xing wrote:

Thank you Vladimir for your detailed explanation! And how do you know the pointer(-4569) points to readable "0" instead of others?

you can try to play with following code.

#include <string.h>
#include <stdio.h>

int has_8bit(int i)
{
    return strcmp((char*)i, "none");
}
int main(void){
    int *NISLParameter0 = -4569;
    printf("%d\n",*NISLParameter0);
    printf("%s\n",(char*)*NISLParameter0);
    int NISLParameter1 = has_8bit(*NISLParameter0);
    printf("%d\n",NISLParameter1);
    return 0;
}

 

0 Kudos
Reply