Thread: sprintf and fprintf segmentation error

  1. #1
    Registered User
    Join Date
    Jun 2005
    Posts
    2

    sprintf and fprintf segmentation error

    Hi there,

    (second try to post thread, was not logon and stupid browser loose all my message...)

    We are doing a migration with our C applications from AIX 4.3 to Linux Red Hat Enterprise 3.0 (kernel 2.4.21-27.ELsmp) and with GCC 3.2.3. We got to runtime error in some executable so far. Looks all the same except some are sprintf and others fprintf errors. Here a GDB backtrace:

    Code:
    [Thread debugging using libthread_db enabled]
    [New Thread 16384 (LWP 14014)]
    Detaching after fork from child process 14017.
    
    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 16384 (LWP 14014)]
    0x001ef703 in strlen () from /lib/i686/libc.so.6
    (gdb) bt
    #0  0x001ef703 in strlen () from /lib/i686/libc.so.6
    #1  0x001bf8d9 in vfprintf () from /lib/i686/libc.so.6
    #2  0x001c67ef in fprintf () from /lib/i686/libc.so.6
    #3  0x0804ee63 in Write_PpiFileFor (Rec_Type_id=0x80612e8 "A1") at ppi_extract.pc:512
    #4  0x08057c80 in Build_CcdRecA1 (r_trnreq=0xbfffcea0, r_emple_info=0xbfffc420) at ppi_extract.pc:2171
    #5  0x0805541e in Build_CcdRecAA (r_trnreq=0xbfffcea0, req_type=0x8061090 "CHQ") at ppi_extract.pc:1624
    #6  0x08054786 in Process_ReqTransFor (req_type=0x8061090 "CHQ") at ppi_extract.pc:1424
    #7  0x0804e297 in MainProcess () at ppi_extract.pc:355
    #8  0x0804e1c3 in main (argc=3, argv=0xbfffe084) at ppi_extract.pc:318
    The program crash at the Write_PpiFileFor function at the fprintf line:

    Code:
    rec_ccd_A1_t        r_ccd_A1;
    
    static long Write_PpiFileFor( char *Rec_Type_id)
    {
        long        result = 0;
        int         i;
        
        WriteTrack("Write_PpiFileFor");
        if (pfiletoccd == (FILE *) NULL) {
            result = DCM_CANNOT_OPEN_FILE;
            Mesg_DCM_LogErr("Write_PpiFileFor", "Cannot open PPI File");
        } else {
    
    /* ... */
    
    if (strcmp(Rec_Type_id, "A1") == UTIL_OK) {
                req_alltrn_rec++;
    
                fprintf(pfiletoccd, "%2s%2s%6s%4s%3s%5s%29s%2s%3s%2s%10s%2s%12s%1018s\n", r_ccd_A1.Rec_Type_Id,
                    CHAR_BLK, r_ccd_A1.POL_NUM, CHAR_BLK, r_ccd_A1.DIV_Num,
                    CHAR_BLK, r_ccd_A1.Participant_Name, CHAR_BLK, r_ccd_A1.Office_Num,
                    CHAR_BLK, r_ccd_A1.Registration_Num, CHAR_BLK, r_ccd_A1.Issued_Dt,CHAR_BLK);
            }
    
    /* ... */
    
    return result;
    
    }
    And here's the structure definition:

    Code:
    typedef struct rec_ccd_A1_s
    {
     char   Rec_Type_Id[2+1];
     char   POL_NUM[6+1];
     char   DIV_Num[3+1];
     char   Participant_Name[29+1];
     char   Office_Num[3+1];
     char   Registration_Num[10+1];
     char   Issued_Dt[12+1];
    } rec_ccd_A1_t;
    I've read in another thread that there's could be a workaround with vsprintf function but our goal is to minimize source code modification because we have a lot of applications to migrate.

    Any idea why this code was running fine on AIX and now with GCC it crash like this? And is there other ways than changing code with vsprintf to resolve that bug?

    Any help would be appreciated, thank you,

    Laurent

  2. #2
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    I think the best way to debug would be to check the values before writing to the file using printf() stmts. Or better yet write one value at a time. Too much of work but patiance is a virtue..

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    2
    I did exactly that nkhambal and found that it is the CHAR_BLK constant that is the culprit. It is define in our include file like this:

    #define CHAR_BLK ' '

    It is a blank space created with the spacebar key. We use that to format the blank spaces between the fields, it must be very precise because this output file is the input for a mainframe COBOL application...

    So if I'm able to replace only the entry in the .h file and not modify the .c files it would be great.

    Thank you,
    Laurent

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    (second try to post thread, was not logon and stupid browser loose all my message...)
    Same thing just happened to me . . . .

    Because of the strlen() error, I'd guess that something like this is happening:

    Code:
    char p = 'a';
    /* ... */
    strlen(p);
    Where p is a char and not a string.

    dwk

  5. #5
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by kona1

    #define CHAR_BLK ' '

    So if I'm able to replace only the entry in the .h file and not modify the .c files it would be great.

    Thank you,
    Laurent
    A great illustration of how macros can make life harder.

    CHAR_BLK is a char. All C library "string" functions (strlen(), printf() with %s format specifier, etc.) work on a pointer to a null-terminated sequence of chars. So, the following is an example of a Bad Thing That Sometimes Acts Like It's OK, depending on where and when (and if) a zero byte is encountered in memory. (It's undefined behavior.)

    Code:
    printf("%s", ' ');
    If you want to print a single space with a %s format, you could do something like this:

    Code:
    printf("%s", " ");
    Of course you (probably) wouldn't do it this way if you were just using this one printf() statement, but if the program is using macros to put a single space at various places in the program's output, you could do something like this:

    Code:
    #define CHAR_BLK " "
    .
    .
    .
    printf("%s", CHAR_BLK);
    Then, printing with %s will work ok. (Man, I really hate to debug code with lots of unnecessary macros --- and most of them are unnecessary and, often, obfuscatory in the extreme.)

    Now, however if you redefine CHAR_BLK to be the string literal, and the program uses CHAR_BLK as a char anywhere in the program, that's bad. Therefore, you must look at all files that #include the header that #defines CHAR_BLK and see how CHAR_BLK is used everywhere in those files. If it's only used as a string consisting of a single space character, then changing the #define in the header file will prevent the particular error shown here.

    One more comment: Note that the following does two things on my system(s):

    Code:
    #include <stdio.h>
    
    #define CHAR_BLK ' '
    
    int main()
    {
      printf("<%s>\n", CHAR_BLK);
      return 0;
    }

    1. When compiled (with gcc) and executed, it gives a "STATUS_ACCESS_VIOLATION" error (also known as seg fault). It also gives execution errors with compiled with Borland or Microsoft compilers and executed on my Windows XP box.

    2. When compiled like this with gcc:
    gcc -Wall test.c
    The compiler tells me this about the line with the printf() statement:
    7: Warning format argument is not a pointer (arg 2)

    So: turn on those compiler warnings!!! (And pay attention to them.)

    Regards,

    Dave
    Last edited by Dave Evans; 06-20-2005 at 05:37 PM.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    if (pfiletoccd == (FILE *) NULL)
    if (strcmp(Rec_Type_id, "A1") == UTIL_OK)
    Random casts, and vague things like UTIL_OK do nothing to improve the readability (or portability) of the code.

    strcmp() returns 3 possible answers, exactly what does UTIL_OK mean?
    It returned without crashing?
    It certainly doesn't help in figuring out whether it means that the result was a successful comparison or not.

    > Any idea why this code was running fine on AIX and now with GCC it crash like this?
    Yeah, the code is crap and your previous compiler swept all the problems under the carpet.
    Essentially, development stopped when the code stopped crashing, not when it was bug-free. The usual scenario when porting to another platform is that a whole bunch of new problems suddenly emerge and you have to do some more work.

    > we have a lot of applications to migrate.
    Time to buy a coffee pot - you're in for some long sessions
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sprintf + fprintf
    By cfdprogrammer in forum C Programming
    Replies: 2
    Last Post: 03-26-2009, 03:44 AM
  2. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  3. Multithreading problem
    By Bacardi34 in forum C Programming
    Replies: 5
    Last Post: 09-02-2004, 02:26 PM
  4. parse error
    By DMaxJ in forum C Programming
    Replies: 7
    Last Post: 06-30-2003, 08:54 PM
  5. telnet
    By MrJake in forum C++ Programming
    Replies: 18
    Last Post: 11-13-2002, 06:21 PM