简体   繁体   中英

Mixed-language program crash occurs when free() called

I have a program where code in C, C++ and Fortran has been compiled and linked together. The main function is written in C++ and is found in file testQ.cpp . The C++ code calls a Fortran subroutine in file getqpf.F . The subroutine in getqpf.F calls C functions in a number of other files.

Using gcc and gfortran on GNU/Linux I have successfully linked together the program:

 g++ -c test-Q.cpp -I./boost/boost_1_52_0/ -g
 gcc -c paul2.c -g
 gcc -c paul2_L1.c -g
 gcc -c paul6.c -g
 gcc -c paul6_L1.c -g 
 gcc -c fit_slope.c -g
 gfortran -c getqpf.F -g
 g++ -o test-Q test-Q.o paul2.o paul2_L1.o paul6.o paul6_L1.o fit_slope.o getqpf.o -g -lgfortran

The program appears to run normally. However, it crashes before terminating when free() is called:

free(x1);

This is the last statement in the program, and the program will only crash when free() is called. Now x1 is created using the following malloc :

double *x1;
x1 = (double*)malloc(iXget);

The x1 pointer is passed in to the Fortran code, and the Fortran subroutine passes it into a C code function.

Here is the output of the crash. What could be going wrong here, and how might I debug this? I've recently installed valgrind . How can I use this to debug my program?

*** glibc detected *** ./test-Q: free(): invalid next size (normal): 0x0000000000f50aa0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7ae16)[0x7feabf64de16]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x7feabf6520fc]
./test-Q[0x402520]
./test-Q[0x4026b2]
./test-Q[0x401dbd]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7feabf5f430d]
./test-Q[0x401cf9]
======= Memory map: ========
00400000-0040b000 r-xp 00000000 08:11 9714095                            /media/RESEARCH/SAS2-version2/test-Q/test-Q
0060a000-0060b000 r--p 0000a000 08:11 9714095                            /media/RESEARCH/SAS2-version2/test-Q/test-Q
0060b000-0060c000 rw-p 0000b000 08:11 9714095                            /media/RESEARCH/SAS2-version2/test-Q/test-Q
00f39000-00f5a000 rw-p 00000000 00:00 0                                  [heap]
7feab8000000-7feab8021000 rw-p 00000000 00:00 0 
7feab8021000-7feabc000000 ---p 00000000 00:00 0 
7feabf39d000-7feabf3d2000 r-xp 00000000 08:01 18881806                   /usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0
7feabf3d2000-7feabf5d1000 ---p 00035000 08:01 18881806                   /usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0
7feabf5d1000-7feabf5d2000 r--p 00034000 08:01 18881806                   /usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0
7feabf5d2000-7feabf5d3000 rw-p 00035000 08:01 18881806                   /usr/lib/x86_64-linux-gnu/libquadmath.so.0.0.0
7feabf5d3000-7feabf76c000 r-xp 00000000 08:01 16515356                   /lib/x86_64-linux-gnu/libc-2.13.so
7feabf76c000-7feabf96b000 ---p 00199000 08:01 16515356                   /lib/x86_64-linux-gnu/libc-2.13.so
7feabf96b000-7feabf96f000 r--p 00198000 08:01 16515356                   /lib/x86_64-linux-gnu/libc-2.13.so
7feabf96f000-7feabf970000 rw-p 0019c000 08:01 16515356                   /lib/x86_64-linux-gnu/libc-2.13.so
7feabf970000-7feabf976000 rw-p 00000000 00:00 0 
7feabf976000-7feabf98b000 r-xp 00000000 08:01 16518820                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7feabf98b000-7feabfb8a000 ---p 00015000 08:01 16518820                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7feabfb8a000-7feabfb8b000 r--p 00014000 08:01 16518820                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7feabfb8b000-7feabfb8c000 rw-p 00015000 08:01 16518820                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7feabfb8c000-7feabfc0f000 r-xp 00000000 08:01 16515346                   /lib/x86_64-linux-gnu/libm-2.13.so
7feabfc0f000-7feabfe0e000 ---p 00083000 08:01 16515346                   /lib/x86_64-linux-gnu/libm-2.13.so
7feabfe0e000-7feabfe0f000 r--p 00082000 08:01 16515346                   /lib/x86_64-linux-gnu/libm-2.13.so
7feabfe0f000-7feabfe10000 rw-p 00083000 08:01 16515346                   /lib/x86_64-linux-gnu/libm-2.13.so
7feabfe10000-7feabfef8000 r-xp 00000000 08:01 18881835                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7feabfef8000-7feac00f8000 ---p 000e8000 08:01 18881835                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7feac00f8000-7feac0100000 r--p 000e8000 08:01 18881835                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7feac0100000-7feac0102000 rw-p 000f0000 08:01 18881835                   /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7feac0102000-7feac0117000 rw-p 00000000 00:00 0 
7feac0117000-7feac022b000 r-xp 00000000 08:01 18883022                   /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0
7feac022b000-7feac042a000 ---p 00114000 08:01 18883022                   /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0
7feac042a000-7feac042b000 r--p 00113000 08:01 18883022                   /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0
7feac042b000-7feac042d000 rw-p 00114000 08:01 18883022                   /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0
7feac042d000-7feac044e000 r-xp 00000000 08:01 16515354                   /lib/x86_64-linux-gnu/ld-2.13.so
7feac0630000-7feac0636000 rw-p 00000000 00:00 0 
7feac064a000-7feac064d000 rw-p 00000000 00:00 0 
7feac064d000-7feac064e000 r--p 00020000 08:01 16515354                   /lib/x86_64-linux-gnu/ld-2.13.so
7feac064e000-7feac0650000 rw-p 00021000 08:01 16515354                   /lib/x86_64-linux-gnu/ld-2.13.so
7fff2940a000-7fff2942b000 rw-p 00000000 00:00 0                          [stack]
7fff2952c000-7fff2952d000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted

UPDATE

After running valgrind --tool=memcheck --leak-check=full --log-file=memcheck.log ./test-Q , I get a rather curious-looking log file. Perhaps something isn't set up properly? Here it is:

==15621== Memcheck, a memory error detector
==15621== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==15621== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==15621== Command: ./test-Q
==15621== Parent PID: 14623
==15621== 
==15621== Invalid write of size 4
==15621==    at 0x401EE2: call_function(std::vector<double, std::allocator<double> >) (test-Q.cpp:183)
==15621==    by 0x4026B1: run_experiment() (test-Q.cpp:346)
==15621==    by 0x401DBC: main (test-Q.cpp:120)
==15621==  Address 0x5ecba78 is 1,000 bytes inside a block of size 1,001 alloc'd
==15621==    at 0x4C2A66F: malloc (vg_replace_malloc.c:270)
==15621==    by 0x401E9A: call_function(std::vector<double, std::allocator<double> >) (test-Q.cpp:179)
==15621==    by 0x4026B1: run_experiment() (test-Q.cpp:346)
==15621==    by 0x401DBC: main (test-Q.cpp:120)
==15621== 
--15621-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--15621-- si_code=80;  Faulting address: 0x0;  sp: 0x4030e0df0

valgrind: the 'impossible' happened:
   Killed by fatal signal
==15621==    at 0x380624A6: vgPlain_arena_malloc (m_mallocfree.c:291)
==15621==    by 0x380294E4: vgMemCheck_new_block (mc_malloc_wrappers.c:263)
==15621==    by 0x3802967A: vgMemCheck_malloc (mc_malloc_wrappers.c:301)
==15621==    by 0x3809D05D: vgPlain_scheduler (scheduler.c:1665)
==15621==    by 0x380AC715: run_a_thread_NORETURN (syswrap-linux.c:103)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable
==15621==    at 0x4C2A66F: malloc (vg_replace_malloc.c:270)
==15621==    by 0x401FB9: call_function(std::vector<double, std::allocator<double> >) (test-Q.cpp:217)
==15621==    by 0x4026B1: run_experiment() (test-Q.cpp:346)
==15621==    by 0x401DBC: main (test-Q.cpp:120)


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.

UPDATE

Here is the function in question with the array.

// main function
int main()
{
    run_experiment();   
} 


void run_experiment()
{

    const int MAX_VAL = 1001;
    std::string line;
    std::ifstream myfile ("s1.txt");
    std::vector<double>data(MAX_VAL);
    int cnt = 0;
    double val;


    if (myfile.is_open())
    {
        while ( myfile.good() && cnt < MAX_VAL)
        {
            std::getline (myfile,line); 
            val = boost::lexical_cast<double>(line);
            data[cnt++] = val;      
        }
        myfile.close();

        // data vector seems to be OK here          


        // call the function to do the data processing
        // this is the line 346 called into question by Valgrind
        // run_experiment() (test-Q.cpp:346)
        call_function(data);    

    }
    else std::cout << "Unable to open file"; 
} // end

Here is the function declaration. The vector is being passed by value.

void call_function(std::vector<double> v);

UPDATE

As astutely suggested by mux in an answer below, it is indeed a problem with writing beyond the bounds of an array. Here is the version of the code that works, with the wrong code shown in the comments. I modified the vector to hold elements of type float , but the real issue was indeed writing beyond the bounds of an array.

The C-style array was created using malloc() , but the sizeof() function had to be used to create adequate space.

Changing this one line of code causes the error to go away.

 // function to call code in the q analysis function
    void call_function(std::vector<float> v)
    {

        // create all of the inputs
        float *tri = NULL; 
        int nsamp;
        int lwin;
        int nfreqfit;   // calculated below 
        float dt;  
        float null;  
        int L2; 
        float df;       // calculated below
        float *qq = NULL;  
        float *pf = NULL; 
        float *ampls;  
        double *work1; 
        double *work2; 
        double *work3; 
        double *work4; 
        int mem; 
        int morder;
        int nfs;        // calculated below
        double *xReal = NULL;  
        double *xImag = NULL; 
        double *xAbs = NULL;
        double *x1 = NULL;
        int cen;
        int top;
        int bot; 
        float cut;
        int nfst;           // calculated below
        int raw;
        float fst;          // low frequency to fit; replaces fpeak frequency


        nsamp = v.size();
        lwin = 101;
        dt =  0.0042;
        null = 100;
        L2 = 1;
        mem = 0;            // keep this as is
        morder = 5;
        cen = 1;
        top = 0;
        bot = 0;
        cut = 0.50;
        raw = 1;
        fst = 0.0;          // lowest frequency to fit


        // this is the line that was changed
        tri = (float*)malloc(nsamp * sizeof(float));

        // This is the line that needed changing
        // tri = (float*)malloc(nsamp);

        // copy the data into the vector
        for (int i = 0; i < nsamp; i++)
            tri[i] = v[i];

       std::cout << "Done copying data to the vector" << std::endl;

    // more code here...

    } // end of function


    void run_experiment()
    {

        const int MAX_VAL = 1001;
        std::string line;
        std::ifstream myfile ("s1.txt");
        std::vector<float>data(MAX_VAL);
        int cnt = 0;
        float val;


        if (myfile.is_open())
        {
            while ( myfile.good() && cnt < MAX_VAL)
            {
                std::getline (myfile,line); 
                val = boost::lexical_cast<double>(line);
                data[cnt++] = val;      
            }
            myfile.close();

            /*
            for (int i = 0; i < 1001; i++)
                std::cout << data[i] << std::endl;
            */


            // call the function to do the data processing
            call_function(data);    

        }
        else std::cout << "Unable to open file"; 
    } // end


int main()
{
    run_experiment();   
} 

It looks like you have a memory leak somewhere in your program, the output you provided isn't really helpful at all, you should run the program with valgrind to figure the problem. Try:

valgrind --tool=memcheck --leak-check=full --log-file=memcheck.log <binary>

If you fork any child processes you may want to add:

--trace-children=yes

Then post the memcheck.log and the relevant code if you still can't fix it.

Edit: it seems that you're writing beyond the bounds of some array here:

call_function(std::vector<double, std::allocator<double> >) (test-Q.cpp:183)

You should fix that first, it could be the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM