An example with unrestricted union class that holds either a map of ints or a vector of ints:
#include <iostream>
#include <string>
#include <vector>
#include <map>
typedef std::vector<int> int_vec;
typedef std::map<std::string, int> int_map;
struct Vec {
bool is_map;
union {
int_vec int_vec_val;
int_map int_map_val;
};
// MOVE CONSTRUCTORS
Vec(int_vec&& val) : is_map(false), int_vec_val(std::move(val)) {
std::cout << "move vec" << std::endl;
}
Vec(int_map&& val) : is_map(true), int_map_val(std::move(val)) {
std::cout << "move map" << std::endl;
}
Vec(Vec&& rhs) : is_map(rhs.is_map) {
if (is_map) {
int_map_val = std::move(rhs.int_map_val);
} else {
std::cout << "Crashing now ... " << std::endl;
int_vec_val = std::move(rhs.int_vec_val); // <--- how to do this correctly?
}
}
// DESTRUCTOR
~Vec() noexcept {
if (is_map) {
int_map_val.~int_map();
} else {
int_vec_val.~int_vec();
}
}
};
Vec gen_Vec() {
Vec v1(int_vec({1, 2, 3}));
return Vec(std::move(v1));
}
int main() {
Vec v2 = gen_Vec();
}
This code crashes with *** Error in ./tmp2: munmap_chunk(): invalid pointer: 0x0000000000400f6d *** in the Vec(Vec&&) move constructor:
g++ -std=c++11 -O2 tmp2.cpp -lm -o tmp2 && ./tmp2
move vec
Crashing now ...
*** Error in `./tmp2': munmap_chunk(): invalid pointer: 0x0000000000400f6d ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fba03ab47e5]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7fba03ac0ae8]
./tmp2[0x400d0d]
./tmp2[0x400a7c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fba03a5d830]
./tmp2[0x400af9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:11 13240011 /store/Dropbox/dev/jamr/src/tmp2
00601000-00602000 r--p 00001000 08:11 13240011 /store/Dropbox/dev/jamr/src/tmp2
00602000-00603000 rw-p 00002000 08:11 13240011 /store/Dropbox/dev/jamr/src/tmp2
006ce000-00700000 rw-p 00000000 00:00 0 [heap]
7fba03734000-7fba0383c000 r-xp 00000000 08:01 1065106 /lib/x86_64-linux-gnu/libm-2.23.so
7fba0383c000-7fba03a3b000 ---p 00108000 08:01 1065106 /lib/x86_64-linux-gnu/libm-2.23.so
7fba03a3b000-7fba03a3c000 r--p 00107000 08:01 1065106 /lib/x86_64-linux-gnu/libm-2.23.so
7fba03a3c000-7fba03a3d000 rw-p 00108000 08:01 1065106 /lib/x86_64-linux-gnu/libm-2.23.so
My questions are:
What is the correct way to move those vectors and maps?
Is there a way to define Vec(Vec&& rhs) move constructor entirely in the mem initializer list?
Many thanks.
The assignment int_vec_val = std::move(rhs.int_vec_val); implies that int_vec_val denotes an existing, live object of type int_vec and you want to change its value by assigning to it. This is not the case: since the members of the anonymous union don't have default member initializers and don't have corresponding mem-initializers either, no initialization is performed on them, so their lifetimes don't start.
This means that none of int_map_val and int_vec_val is alive when the constructor's block is entered. You have to actually construct a new object of the right type in the right place using placement new:
Vec(Vec&& rhs) : is_map(rhs.is_map) {
if (is_map) {
std::cout << "move contained map\n";
new(&int_map_val) int_map(std::move(rhs.int_map_val));
} else {
std::cout << "move contained vec\n";
new(&int_vec_val) int_vec(std::move(rhs.int_vec_val));
}
}
The answer to your second question is: no, not really, since rhs.is_map is generally only known at run time and the contents of the mem-initializer-list needs to be known at compile time. However, in this case there's no problem with doing the initialization in the constructor's block (and no real benefit to be gained by doing it in the ctor-initializer), since no initialization is performed on the union members by default.
I am new to mmap and still learning it . Based on my understanding i have created class for mmap which will be used to map a file in memory . The entire class is working fine but problem is coming when destructor is called ..the problem is segmentation fault or invalid pointer error is coming at the end of main function ...I have posted code of my class and main function which is using that class ...
Map.h
class MapData
{
public :
MapData();
~MapData();
MapData(char []);
bool OPEN();
void fnClose();
long fnGetSize();
char * fnGetFileRef();
char * ReadNextData(int );
private :
char * ptrRecord;
char ptrFileNm[250+1];
int fd;
struct stat sbuf;
bool bSuccess;
long sTotalSize;
char acData[2000+1];
long lCurrRead;
};
MapData.cpp
MapData::MapData()
{
}
MapData::~MapData()
{
printf("Inside MADATA Destructor \n ");
}
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}
bool MapData::OPEN()
{
// if failed return false flg
if ((fd = open(ptrFileNm, O_RDONLY)) == -1) {
return bSuccess;
}
if (stat(ptrFileNm, &sbuf) == -1) {
return bSuccess;
}
// copy in local variable
sTotalSize = sbuf.st_size;
ptrRecord = (char * )mmap( (caddr_t)0, sTotalSize, PROT_READ, MAP_SHARED, fd, 0) ;
if (ptrRecord == (char *)(caddr_t)(-1) ) {
perror("Fail to Map Data ");
return bSuccess;
}
else
{
printf("Successfully Map Data***[%ld] \n",sTotalSize);
bSuccess=true;
}
return bSuccess;
}
char * MapData::fnGetFileRef()
{
return ptrRecord;
}
char * MapData::ReadNextData(int iX)
{
if((lCurrRead+iX)<sTotalSize)
{
memset(acData,0x00,sizeof(acData));
strncpy(acData,ptrRecord+lCurrRead,iX);
acData[iX+1]='\0';
lCurrRead+=iX;
}else{
strcpy(acData,"ZZZ");
}
return acData;
}
long MapData::fnGetSize()
{
return sTotalSize;
}
void MapData::fnClose()
{
// Don't forget to free the mmapped memory
if(munmap(ptrRecord, sTotalSize) == -1)
{
close(fd);
perror("Error un-mmapping the file");
exit(EXIT_FAILURE);
}
// Un-mmaping doesn't close the file, so we still need to do that.
close(fd);
printf("CLOSED SUCCESSFULLY \n ");
}
Main.cpp
int main()
{
char acFileNm[500+1];
MEMSET(acFileNm); // clean the variable
// file name to be read
strcpy(acFileNm,"ABDFILE.txt");
long lProcCnt=0; // no of byte read by program
char acLine[MAX_LINE_LENGTH+1]; // hold current read line
bool bFlag=true; // main flag
DEBUG_PRINT("File to be processed:%s \n",acFileNm);
// create object of mmap
MapData * pt1 = NULL;
pt1 = new MapData(acFileNm);
if(!pt1)
{
cout<<"Error creating object so quit ..."<<endl;
return 0 ;
}
auto_ptr<MapData> ptrMap( pt1 ); // pass ownership to auto deletor to delete memory
DEBUG_PRINT("STEP1:%s \n","OBJECT CREATION FOR FILE MAPPED IN MEMORY");
// try to open the file
if(ptrMap->OPEN())
{
// on success..get pointer to first char of file
char * ptrData = ptrMap->fnGetFileRef();
long lCompSize=ptrMap->fnGetSize(); // total no of bytes = fiexed line size * no of row + (no of row * EOL)
short int iEOL=0;
// logic to identify file generated on ewhich OS
if( (*(ptrData+MAX_LINE_LENGTH) == '\r') && (*(ptrData+MAX_LINE_LENGTH+1) == '\n'))
{
// DOS format CRLF
iEOL = 2;
}else if(*(ptrData+MAX_LINE_LENGTH) == '\n'){
// Unix format LF
iEOL = 1;
}
DEBUG_PRINT("STEP2: SIZEOFFILE%ld FILESYSTEM FORMAT:%d \n",lCompSize,iEOL);
// here read till it reaches maximum limit of file
while(lProcCnt<lCompSize)
{
//DEBUG_PRINT("PROC COUNTER[%ld] MAX_COUNTER[%ld] \n",lProcCnt,lCompSize);
lProcCnt+=MAX_LINE_LENGTH+iEOL; // increement no of bytes read at initial
MEMSET(acLine);
strncpy(acLine,ptrData+lProcCnt,MAX_LINE_LENGTH); // read line
acLine[MAX_LINE_LENGTH+1]='\0';
// process the line :function is called here to process the line
}
}else{
DEBUG_PRINT("MAP DATA FAILED OF FILE[%s] \n",acFileNm);
bFlag=false;
}
// at the end check if all the controls are matched
if(bFlag)
DEBUG_PRINT("END OF FILE PROCESSING SUCCESS \n");
else
DEBUG_PRINT("END OF FILE PROCESSING FAILED \n");
// close the memory map
ptrMap->fnClose();
MapData * ptr5 = ptrMap.release(); // release the ownership
delete ptr5; **// segmentation fault comes here ...**
}
Please suggest me where i am going wrong since gdb is also not helping ...detailed explanation will be good for me to understand ...
Stacktrace generated by gdb:
*** glibc detected *** DemoMap: free(): invalid pointer: 0x0804c000 ***
======= Backtrace: =========
/lib/libc.so.6[0x9bbc81]
/lib/libc.so.6[0x9be562]
/usr/lib/libstdc++.so.6(_ZdlPv+0x22)[0x544552]
DemoMap[0x80491e6]
/lib/libc.so.6(__libc_start_main+0xe6)[0x961d36]
DemoMap[0x8048d91]
======= Memory map: ========
00110000-00111000 r-xp 00000000 00:00 0 [vdso]
0044c000-00469000 r-xp 00000000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00469000-0046a000 rw-p 0001d000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00495000-00576000 r-xp 00000000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
00576000-0057a000 r--p 000e0000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057a000-0057c000 rw-p 000e4000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057c000-00582000 rw-p 00000000 00:00 0
00929000-00947000 r-xp 00000000 08:03 1065 /lib/ld-2.12.so
00947000-00948000 r--p 0001d000 08:03 1065 /lib/ld-2.12.so
00948000-00949000 rw-p 0001e000 08:03 1065 /lib/ld-2.12.so
0094b000-00adb000 r-xp 00000000 08:03 1067 /lib/libc-2.12.so
00adb000-00adc000 ---p 00190000 08:03 1067 /lib/libc-2.12.so
00adc000-00ade000 r--p 00190000 08:03 1067 /lib/libc-2.12.so
00ade000-00adf000 rw-p 00192000 08:03 1067 /lib/libc-2.12.so
00adf000-00ae2000 rw-p 00000000 00:00 0
00b29000-00b51000 r-xp 00000000 08:03 1211 /lib/libm-2.12.so
00b51000-00b52000 r--p 00027000 08:03 1211 /lib/libm-2.12.so
00b52000-00b53000 rw-p 00028000 08:03 1211 /lib/libm-2.12.so
08048000-0804b000 r-xp 00000000 08:08 2883976 DemoMap
0804b000-0804c000 rw-p 00002000 08:08 2883976 DemoMap
0804c000-0806d000 rw-p 00000000 00:00 0 [heap]
b7e00000-b7e21000 rw-p 00000000 00:00 0
b7e21000-b7f00000 ---p 00000000 00:00 0
b7f9b000-b7fe5000 r--s 00000000 08:08 4326707 ABCDEF.TXT
b7fe5000-b7fe8000 rw-p 00000000 00:00 0
b7ffd000-b8000000 rw-p 00000000 00:00 0
bffeb000-c0000000 rw-p 00000000 00:00 0 [stack]
may be here.
char ptrFileNm[250+1];
char acFileNm[500+1];
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);//segmentation fault
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}
I have one problem. I am trying to get stack offset range from /proc/self/maps pseudofile. But I have sometime weird things.
Here is my code
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
perror("Error opening file");
return NULL;
}
while (fgets(line, 2048, fp) != NULL) {
if (strstr(line, "stack") != NULL) {
printf("%s", line);
}
}
If you start the programm with one or multiple thread you can view this pseudo file and get something like this
7f20423a6000-7f2042ba6000 rw-p 00000000 00:00 0 [stack:3936]
7fffbe95e000-7fffbe97f000 rw-p 00000000 00:00 0 [stack]
the first line here is stack of thread , the second line is the stack of the process.
But the problem is that sometimes I cannot get stack of thread. It can be from the first time or appear on some next execution so it is not determined. On some distos it doesn't show stack of thread at all, I don't think the problem is in different implementation of pseudo file in distros but in something other.
Please help to solve this problem
EDIT
I actually call this function inside thread , so I create thread through pthread_create(&tid, NULL, proc_stack, NULL);I have been also thinking about this. Maybe it needs some time to update this pseudofile after thread start, this is only one reason I see here.
EDIT2
I've tried to call sleep forcely , but this didn't help, but the most weird is that on one distro it shows thread stack, on another doesn't.
On my system Your program also dosn't show second stack segment, but it seems 5 segments are allocated above [heap] and one of them is used for thread stack (local variables of proc_stack() are stored in this segment).
Code I used to check for it (test.c):
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void* proc_stack(void* p){
FILE *fp;
char line[2048];
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
perror("Error opening file");
return NULL;
}
while (fgets(line, 2048, fp) != NULL) {
// if (strstr(line, "stack") != NULL) {
printf("%s", line);
// }
}
printf("addr = %p %p\n", &fp, &line);
return NULL;
}
int main(){
pthread_t tid;
void *rv;
proc_stack( NULL );
puts("main");
pthread_create( &tid, NULL, proc_stack, NULL );
pthread_join( tid, &rv );
return 0;
}
Compiled with gcc -Wall test.c -pthread. Results (some lines removed):
...
01933000-01954000 rw-p 00000000 00:00 0 [heap]
...
7fff75be3000-7fff75c04000 rw-p 00000000 00:00 0 [stack]
7fff75d97000-7fff75d98000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
addr = 0x7fff75c00e68 0x7fff75c00e70
main
...
01933000-01954000 rw-p 00000000 00:00 0 [heap]
7f3be0000000-7f3be0021000 rw-p 00000000 00:00 0
7f3be0021000-7f3be4000000 ---p 00000000 00:00 0
7f3be6b79000-7f3be6b7a000 rw-p 00000000 00:00 0
7f3be6b7a000-7f3be6b7b000 ---p 00000000 00:00 0
7f3be6b7b000-7f3be737b000 rw-p 00000000 00:00 0
...
7fff75be3000-7fff75c04000 rw-p 00000000 00:00 0 [stack]
7fff75d97000-7fff75d98000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
addr = 0x7f3be73796c8 0x7f3be73796d0
I know a lot of people met this problem and I have gone through a lot of them. But I still can't solve my problem. Here is it:
My code is c++ code. But I need to call a shared library made by c (ODE solver) for my problem.
int Reaction::cvodedensewrapper()
This is where the functions of ODE solver are called. My class is Reaction and cvodedenseWrapper() is a class function. I define a struct for data transfer from c++ to c as:
typedef struct {
unsigned int exp_ID, nExp,nRec, nComp;
realtype *Ts;
realtype *dTs;
realtype *ts;
realtype *vkp;
realtype Tr;
} User;
typedef User *UserData;
Here realtype is a name for double type. I define a UserData type variable in my code, allocate memory and initialize it as:
User data;
UserData udata=& data;
udata->Ts=new realtype[numExp];
udata->dTs=new realtype[numExp];
udata->ts=new realtype[numExp];
udata->vkp=new realtype[2*numRec];
udata->nExp=numExp;
udata->nRec=numRec;
udata->nComp=numComp;
udata->Tr=Tref;
for(i=0;i!=numExp;i++)
{
udata->Ts[i]=Tstart[i];
udata->dTs[i]=dT[i];
udata->ts[i]=tstart[i];
}
for(i=0;i!=2*numRec;i++)
{
udata->vkp[i]=vk[i];
}
The udata will be passed to ODE solver six times in a loop. At each time, I monitor the address of the dynamic arrays and its content with the code:
printf("udata->Ts: %p\n",udata->Ts);
for(i=0;i!=numExp;i++)
printf(" Ts[%d]=%.5f ",i,udata->Ts[i]);
printf("\n");
printf("udata->dTs: %p\n",udata->dTs);
for(i=0;i!=numExp;i++)
printf(" dTs[%d]=%.5f ",i,udata->dTs[i]);
printf("\n");
printf("udata->ts: %p\n",udata->ts);
for(i=0;i!=numExp;i++)
printf(" ts[%d]=%.5f ",i,udata->ts[i]);
printf("\n");
printf("udata->vkp: %p\n",udata->vkp);
for(i=0;i!=2*numRec;i++)
printf(" vkp[%d]=%.5f ",i,udata->vkp[i]);
printf("\n");
The output at the first time:
m = 0
udata->Ts: 0x62c430
Ts[0]=673.00000 Ts[1]=698.00000 Ts[2]=723.00000 Ts[3]=748.00000 Ts[4]=773.00000 Ts[5]=798.00000
udata->dTs: 0x638f30
dTs[0]=0.00000 dTs[1]=0.00000 dTs[2]=0.00000 dTs[3]=0.00000 dTs[4]=0.00000 dTs[5]=0.00000
udata->ts: 0x638f70
ts[0]=316.09846 ts[1]=283.41932 ts[2]=253.00015 ts[3]=224.61435 ts[4]=198.06463 ts[5]=173.17842
udata->vkp: 0x62e150
vkp[0]=-4.22868 vkp[1]=-2.73312 vkp[2]=2.80980 vkp[3]=-1.65961 vkp[4]=27.23419 vkp[5]=25.96871vkp[6]=16.03558 vkp[7]=10.69316
As comparison, here is the sixth output,
udata->Ts: 0x62c430
Ts[0]=673.00000 Ts[1]=698.00000 Ts[2]=723.00000 Ts[3]=748.00000 Ts[4]=773.00000 Ts[5]=798.00000
udata->dTs: 0x638f30
dTs[0]=0.00000 dTs[1]=0.00000 dTs[2]=0.00000 dTs[3]=0.00000 dTs[4]=0.00000 dTs[5]=0.00000
udata->ts: 0x638f70
ts[0]=316.09846 ts[1]=283.41932 ts[2]=253.00015 ts[3]=224.61435 ts[4]=198.06463 ts[5]=173.17842
udata->vkp: 0x62e150
vkp[0]=-4.22868 vkp[1]=-2.73312 vkp[2]=2.80980 vkp[3]=-1.65961 vkp[4]=27.23419 vkp[5]=25.96871vkp[6]=16.03558 vkp[7]=10.69316
After the loop, I just use the following syntax to release memory,
delete [] udata->Ts;
delete [] udata->dTs;
delete [] udata->ts;
delete [] udata->vkp;
udata=NULL;
It can be seen the pointer and the content pointer points to keeps the same. Nothing changed. So the problems other met is excluded. And this is the only place I use delete.
ERROR information is as follows:
*** glibc detected *** /home/fenglei/mopso_oil_shale_cvode/mopso: munmap_chunk(): invalid pointer: 0x000000000062e150 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7ffff7286b96]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x405890]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x404b28]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x407482]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x409da5]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x40ba63]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ffff722976d]
/home/fenglei/mopso_oil_shale_cvode/mopso[0x401a09]
======= Memory map: ========
00400000-00429000 r-xp 00000000 08:06 4209122 {directory}/example
00628000-00629000 r--p 00028000 08:06 4209122 {directory}/example
00629000-0062a000 rw-p 00029000 08:06 4209122 {directory}/example
0062a000-0064b000 rw-p 00000000 00:00 0 [heap]
7ffff7208000-7ffff73bd000 r-xp 00000000 08:06 131963 /lib/x86_64- linux-gnu/libc-2.15.so
7ffff73bd000-7ffff75bd000 ---p 001b5000 08:06 131963 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff75bd000-7ffff75c1000 r--p 001b5000 08:06 131963 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff75c1000-7ffff75c3000 rw-p 001b9000 08:06 131963 /lib/x86_64-linux-gnu/libc-2.15.so
7ffff75c3000-7ffff75c8000 rw-p 00000000 00:00 0
7ffff75c8000-7ffff75dd000 r-xp 00000000 08:06 134855 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff75dd000-7ffff77dc000 ---p 00015000 08:06 134855 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff77dc000-7ffff77dd000 r--p 00014000 08:06 134855 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff77dd000-7ffff77de000 rw-p 00015000 08:06 134855 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff77de000-7ffff78d9000 r-xp 00000000 08:06 131976 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff78d9000-7ffff7ad8000 ---p 000fb000 08:06 131976 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7ad8000-7ffff7ad9000 r--p 000fa000 08:06 131976 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7ad9000-7ffff7ada000 rw-p 000fb000 08:06 131976 /lib/x86_64-linux-gnu/libm-2.15.so
7ffff7ada000-7ffff7bbc000 r-xp 00000000 08:06 5250632 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7bbc000-7ffff7dbb000 ---p 000e2000 08:06 5250632 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dbb000-7ffff7dc3000 r--p 000e1000 08:06 5250632 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dc3000-7ffff7dc5000 rw-p 000e9000 08:06 5250632 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7ffff7dc5000-7ffff7dda000 rw-p 00000000 00:00 0
7ffff7dda000-7ffff7dfc000 r-xp 00000000 08:06 131977 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7fdc000-7ffff7fe1000 rw-p 00000000 00:00 0
7ffff7ff6000-7ffff7ffa000 rw-p 00000000 00:00 0
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00022000 08:06 131977 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff7ffd000-7ffff7fff000 rw-p 00023000 08:06 131977 /lib/x86_64-linux-gnu/ld-2.15.so
7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Program received signal SIGABRT, Aborted.
0x00007ffff723e425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
This is the first time I post my questions here, although i got a lot of stuff from this website. I hope I made my problem clear.
Code:
/*
---------------------------------
*ODE problem solver definition
---------------------------------
*/
#include <stdio.h>
/* Header files with a description of contents used */
#include <cvode/cvode.h> /* prototypes for CVODE fcts., consts. */
#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., macros */
#include <cvode/cvode_dense.h> /* prototype for CVDense */
#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
#include <sundials/sundials_types.h> /* definition of type realtype */
/* User-defined vector and matrix accessor macros: Ith, IJth */
/* These macros are defined in order to write code which exactly matches
the mathematical problem description given above.
Ith(v,i) references the ith component of the vector v, where i is in
the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
using the N_VIth macro in nvector.h. N_VIth numbers the components of
a vector starting from 0.
IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
i and j are in the range [1..NEQ]. The IJth macro is defined using the
DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
dense matrix starting from 0. */
#define Ith(v,i) NV_Ith_S(v,i-1) /* Ith numbers components 1..NEQ */
#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
/* Problem Constants */
#define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
#define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
#define ATOL2 RCONST(1.0e-8)
#define ATOL3 RCONST(1.0e-8)
#define ATOL4 RCONST(1.0e-8)
#define Y(i) yt[i-1]
#define K(i) kt[i-1]
typedef struct {
unsigned int exp_ID, nExp,nRec, nComp;
realtype *Ts;
realtype *dTs;
realtype *ts;
realtype *vkp;
realtype Tr;
} User;
typedef User *UserData;
/* Functions Called by the Solver */
static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
static int Jac(long int N, realtype t,
N_Vector y, N_Vector fy, DlsMat J, void *user_data,
N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
/* Private function to check function return values */
static int check_flag(void *flagvalue, const char *funcname, int opt);
int Reaction::cvodedensewrapper()
{
int i=0,j=0,k=0,m=0,numt;
realtype reltol,t,tout,ts;
N_Vector y, abstol;
void *cvode_mem;
int iout, flag;
User data;
UserData udata=& data;
/*Allocation and initialization*/
udata->Ts=new realtype[numExp];
udata->dTs=new realtype[numExp];
udata->ts=new realtype[numExp];
udata->vkp=new realtype[2*numRec];
udata->nExp=numExp;
udata->nRec=numRec;
udata->nComp=numComp;
udata->Tr=Tref;
for(i=0;i!=numExp;i++)
{
udata->Ts[i]=Tstart[i];
udata->dTs[i]=dT[i];
udata->ts[i]=tstart[i];
}
for(i=0;i!=2*numRec;i++)
{
udata->vkp[i]=vk[i];
}
/*for debugging*/
printf("udata->Ts: %p\n",udata->Ts);
for(i=0;i!=numExp;i++)
printf(" Ts[%d]=%.5f ",i,udata->Ts[i]);
printf("\n");
printf("udata->dTs: %p\n",udata->dTs);
for(i=0;i!=numExp;i++)
printf(" dTs[%d]=%.5f ",i,udata->dTs[i]);
printf("\n");
printf("udata->ts: %p\n",udata->ts);
for(i=0;i!=numExp;i++)
printf(" ts[%d]=%.5f ",i,udata->ts[i]);
printf("\n");
printf("udata->vkp: %p\n",udata->vkp);
for(i=0;i!=2*numRec;i++)
printf(" vkp[%d]=%.5f ",i,udata->vkp[i]);
printf("\n");
/*debugging end*/
y = abstol = NULL;
cvode_mem = NULL;
/* Create serial vector of length numRec for I.C. and abstol */
y = N_VNew_Serial(numComp);
if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
abstol = N_VNew_Serial(numComp);
if (check_flag((void *)abstol, "N_VNew_Serial", 0)) return(1);
/* Initialize y */
for(i=0;i!=numComp;i++)
{
//Ith(y,i)=Yinitial[0][i-1];
NV_Ith_S(y,i)=Yinitial[0][i];
}
/*Initialize tstart*/
ts=tstart[0];
/* Set the scalar relative tolerance */
reltol = RTOL;
/* Set the vector absolute tolerance */
Ith(abstol,1)=ATOL1;
Ith(abstol,2)=ATOL2;
Ith(abstol,3)=ATOL3;
Ith(abstol,4)=ATOL3;
/* Call CVodeCreate to create the solver memory and specify the
* Backward Differentiation Formula and the use of a Newton iteration */
cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
/* Set the pointer to user-defined data*/
flag=CVodeSetUserData(cvode_mem,udata);
if(check_flag((void *) cvode_mem,"CVodeCreate",0)) return(1);
/* Call CVodeInit to initialize the integrator memory and specify the
* user's right hand side function in y'=f(t,y), the inital time T0, and
* the initial dependent variable vector y. */
flag = CVodeInit(cvode_mem, f, ts, y);
if (check_flag(&flag, "CVodeInit", 1)) return(1);
/* Call CVodeSVtolerances to specify the scalar relative tolerance
* and vector absolute tolerances */
flag = CVodeSVtolerances(cvode_mem, reltol, abstol);
if (check_flag(&flag, "CVodeSVtolerances", 1)) return(1);
/* Call CVDense to specify the CVDENSE dense linear solver */
flag = CVDense(cvode_mem, numComp);
if (check_flag(&flag, "CVDense", 1)) return(1);
/* Set the Jacobian routine to Jac (user-supplied) */
flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
/* In loop, call CVode, print results, and test for error.
Break out of loop when NOUT preset output times have been reached. */
for (m=0;m!=numExp;m++) {
numt=(int)(tend[m]-tstart[m])/dtsave[m]+1;
udata->exp_ID=m;
Yt[m].tvector[0]=tstart[m];
Yt[m].Tvector[0]=Tstart[m];
for(i=0;i!=numComp;i++)
{
Yt[m].resp[i][0]=Yinitial[m][i];
}
for(i=0;i!=numComp;i++)
{
//Ith(y,i)=Yinitial[m][i-1];
NV_Ith_S(y,i)=Yinitial[m][i];
}
ts=tstart[m];
flag = CVodeReInit(cvode_mem,ts, y);
iout = 0;
tout = tstart[m]+dtsave[m];
while(1) {
flag = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
if (check_flag(&flag, "CVodeInit", 1)) return(1);
if (flag == CV_SUCCESS) {
iout++;
tout=t+dtsave[m];
}
Yt[m].tvector[iout]=t;
Yt[m].Tvector[iout]=Tstart[m]+(Yt[m].tvector[iout]-Yt[m].tvector[0])*dT[m];
for(i=0;i!=numComp;i++)
{
//Yt[m].resp[i-1][iout]=Ith(y,i);
Yt[m].resp[i][iout]=NV_Ith_S(y,i);
}
if (iout == numt) break;
}
/*for debugging*/
printf("udata->Ts: %p\n",udata->Ts);
for(i=0;i!=numExp;i++)
printf(" Ts[%d]=%.5f ",i,udata->Ts[i]);
printf("\n");
printf("udata->dTs: %p\n",udata->dTs);
for(i=0;i!=numExp;i++)
printf(" dTs[%d]=%.5f ",i,udata->dTs[i]);
printf("\n");
printf("udata->ts: %p\n",udata->ts);
for(i=0;i!=numExp;i++)
printf(" ts[%d]=%.5f ",i,udata->ts[i]);
printf("\n");
printf("udata->vkp: %p\n",udata->vkp);
for(i=0;i!=2*numRec;i++)
printf(" vkp[%d]=%.5f ",i,udata->vkp[i]);
printf("\n");
/*debugging end*/
}
/*Free userdata*/
delete [] udata->Ts;
delete [] udata->dTs;
delete [] udata->ts;
delete [] udata->vkp;
udata=NULL;
/*Free ODE solver array*/
N_VDestroy_Serial(y);
N_VDestroy_Serial(abstol);
/* Free integrator memory */
CVodeFree(&cvode_mem);
return(0);
}
/*
*-------------------------------
* Functions called by the solver
*-------------------------------
*/
/*
* f routine. Compute function f(t,y).
*/
/*
* Jacobian routine. Compute J(t,y) = df/dy. *
*/
Functions with CV initils are from shared libraries.
Your problem is almost certainly in the code you didn't show.
According to documentation for CVodeSetUserData, it simply passes UserData through to the function that the solver will eventually invoke (f in this case).
In any case, the tool that will point you straight at your bug is Valgrind. Just run your program under it, and it will tell you exactly how you are corrupting your heap.
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.