Related
I have a very old gameserver file for a video-game that became obsolete years ago (more than a decade and a half has passed since then). A lot of clones and reverse-engineered copycats of this engine exist, but nothing will ever be like the real thing, or at least without tons and tons of work (it's a MMORPG server). It's so old that it uses LinuxThreads instead of NPTL, and uses it for its thread-per-connection architecture (up to 1100 simmultaneos connections interacting with a huge 2D tilebased game world).
I was trying to rewrite it from scratch, since it has ancient GCC debug info available, but had to drop it since the amount of work to do was insane. Now I'm trying to inject new functionality into it, but couldn't proggress any further since I don't really understand how I'm supposed to inject into it.
I've tried coding a very simple injector using ptrace, but the server dies because of a segmentation fault (SIGSEGV) and since I can't attach GDB, I don't really know where the crash is happening.
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#define EMPTY_ADDR 0x80EF000UL
const char *SHELLCODE = "\x90\x90\x90\x90\x90\x90\x90\x90";
pid_t GamePID;
void GetGamePID() {
FILE *fp = fopen("/home/bob/lock.pid", "rb");
if (!fp) {
printf(":: [Error] Game not running.\n");
return;
}
fscanf(fp, "%d", &GamePID);
}
int main() {
GetGamePID();
if (!GamePID)
return 0;
if (ptrace(PTRACE_ATTACH, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot attach.\n");
printf(":: # Fail %d: %s.\n", errno, strerror(errno));
return 0;
}
siginfo_t info;
waitid(P_PID, GamePID, &info, WSTOPPED);
printf(":: [Info] Attach on PID %d.\n", GamePID);
struct user_regs_struct oldregs, regs;
if (ptrace(PTRACE_GETREGS, GamePID, NULL, &oldregs)) {
printf(":: [Error] Cannot save registers (Fail %d).\n", errno);
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
unsigned long save[2];
save[0] = ptrace(PTRACE_PEEKTEXT, GamePID, (void *)(EMPTY_ADDR), NULL);
save[1] = ptrace(PTRACE_PEEKTEXT, GamePID, (void *)(EMPTY_ADDR + 8UL), NULL);
size_t payload_size = strlen(SHELLCODE);
uint64_t *payload = (uint64_t *)SHELLCODE;
printf("[*] Injecting payload at address 0x%lx.\n", EMPTY_ADDR);
for (size_t i = 0; i < payload_size; i += 8, payload++) {
if (ptrace(PTRACE_POKETEXT, GamePID, EMPTY_ADDR + i, *payload) < 0) {
printf(":: [Error] Failed to PTRACE_POKETEXT: %s\n", strerror(errno));
return 1;
}
}
regs = oldregs;
regs.rip = EMPTY_ADDR;
if (ptrace(PTRACE_SETREGS, GamePID, NULL, ®s)) {
printf(":: [Error] Cannot modify registers.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_CONT, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot run shellcode.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
waitid(P_PID, GamePID, &info, WSTOPPED);
// I used blank r-xp space but just in case...
if (ptrace(PTRACE_POKETEXT, GamePID, (void *)(EMPTY_ADDR), (void *)save[0]) ||
ptrace(PTRACE_POKETEXT, GamePID, (void *)(EMPTY_ADDR + 8UL), (void *)save[1])) {
printf(":: [Error] Cannot restore origcode.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_SETREGS, GamePID, NULL, &oldregs)) {
printf(":: [Error] Cannot restore registers.\n");
ptrace(PTRACE_DETACH, GamePID, NULL, NULL);
return 1;
}
if (ptrace(PTRACE_DETACH, GamePID, NULL, NULL)) {
printf(":: [Error] Cannot detach from process.\n");
return 1;
}
puts("[+] Done.");
}
That's how my injector looks like. Strings and whatnot is hardcoded because this is dummy code. Here is /proc/pid/maps output:
08047000-08048000 rwxp 00000000 08:01 549662 /home/bob/bin/game.orig
08048000-08125000 r-xp 00001000 08:01 549662 /home/bob/bin/game.orig
08125000-08129000 rwxp 000dd000 08:01 549662 /home/bob/bin/game.orig
08129000-0eb45000 rwxp 00000000 00:00 0
0f3e2000-14f10000 rwxp 00000000 00:00 0 [heap]
c573f000-f7b69000 rwxp 00000000 00:00 0
f7b6a000-f7b71000 rwxs 00000000 00:01 32821 /SYSV0000271b (deleted)
f7b71000-f7b72000 rwxp 00000000 00:00 0
f7bb5000-f7beb000 rwxp 00000000 00:00 0
f7bec000-f7d3e000 rwxp 00000000 00:00 0
f7d3e000-f7e57000 r-xp 00000000 08:01 1041510 /home/bob/lib/libc.so.6
f7e57000-f7e59000 r-xp 00119000 08:01 1041510 /home/bob/lib/libc.so.6
f7e59000-f7e5b000 rwxp 0011b000 08:01 1041510 /home/bob/lib/libc.so.6
f7e5b000-f7e5d000 rwxp 00000000 00:00 0
f7e5d000-f7e66000 r-xp 00000000 08:01 1041511 /home/bob/lib/libgcc_s.so.1
f7e66000-f7e67000 rwxp 00009000 08:01 1041511 /home/bob/lib/libgcc_s.so.1
f7e67000-f7e68000 rwxp 00000000 00:00 0
f7e68000-f7e8c000 r-xp 00000000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8c000-f7e8d000 r-xp 00023000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8d000-f7e8e000 rwxp 00024000 08:01 1041512 /home/bob/lib/libm.so.6
f7e8e000-f7f3d000 r-xp 00000000 08:01 1041514 /home/bob/lib/libstdc++.so.5
f7f3d000-f7f42000 rwxp 000ae000 08:01 1041514 /home/bob/lib/libstdc++.so.5
f7f42000-f7f47000 rwxp 00000000 00:00 0
f7f47000-f7f56000 r-xp 00000000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f56000-f7f57000 r-xp 0000e000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f57000-f7f58000 rwxp 0000f000 08:01 1041513 /home/bob/lib/libpthread.so.0
f7f58000-f7f9b000 rwxp 00000000 00:00 0
f7f9b000-f7f9e000 r--p 00000000 00:00 0 [vvar]
f7f9e000-f7f9f000 r-xp 00000000 00:00 0 [vdso]
f7f9f000-f7fb8000 r-xp 00000000 08:01 1041509 /home/bob/lib/ld-linux.so.2
f7fb8000-f7fb9000 r-xp 00018000 08:01 1041509 /home/bob/lib/ld-linux.so.2
f7fb9000-f7fba000 rwxp 00019000 08:01 1041509 /home/bob/lib/ld-linux.so.2
ff000000-ff001000 ---p 00000000 00:00 0
ff001000-ff200000 rwxp 00000000 00:00 0
ff200000-ff201000 ---p 00000000 00:00 0
ff201000-ff400000 rwxp 00000000 00:00 0
ff400000-ff401000 ---p 00000000 00:00 0
ff401000-ff600000 rwxp 00000000 00:00 0
ff600000-ff601000 ---p 00000000 00:00 0
ff601000-ff800000 rwxp 00000000 00:00 0
fff4b000-fffa2000 rwxp 00000000 00:00 0 [stack]
My server spawns each thread as an independent process, and as you can see I had to use my libraries (/home/bob/lib) copied from and ancient RedHat version which was compatible with the threading model (getpid() returns a different value for each thread).
I would really like to hear some suggestions on how I can inject new code. Is it just as hacky as writing directly to /proc/pid/mem? How would I override a game function (say, HandlePlayerMove) with /proc/pid/mem? Is it possible to inject a shared object using LD_PRELOAD given that it was compiled against a newer version of libc, libm, etc? Is there a way of knowing what's triggering SIGSEGV without ptrace failing?
edit: dummy code typo
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;
}
As stated on the topic, i'm using objcopy to load SDL_Image images with MinGW over Eclipse Helios for windows.
I'm using the command: objcopy --input-target binary --output-target pei-i386 --binary-architecture i386 Lilothyn.jpg Lilothyn.o
That results in the file:
Lilothyn.o: file format pei-i386
Lilothyn.o
architecture: i386, flags 0x00000030:
HAS_SYMS, HAS_LOCALS
start address 0x00000000
Characteristics 0x305
relocations stripped
line numbers stripped
32 bit words
debugging information removed
Time/Date Thu Jan 01 00:00:00 1970
Magic 0000
MajorLinkerVersion 0
MinorLinkerVersion 0
SizeOfCode 00000000
SizeOfInitializedData 00000000
SizeOfUninitializedData 00000000
AddressOfEntryPoint 00000000
BaseOfCode 00000000
BaseOfData 00000000
ImageBase 00000000
SectionAlignment 00000000
FileAlignment 00000000
MajorOSystemVersion 0
MinorOSystemVersion 0
MajorImageVersion 0
MinorImageVersion 0
MajorSubsystemVersion 0
MinorSubsystemVersion 0
Win32Version 00000000
SizeOfImage 00000000
SizeOfHeaders 00000000
CheckSum 00000000
Subsystem 00000000 (unspecified)
DllCharacteristics 00000000
SizeOfStackReserve 00000000
SizeOfStackCommit 00000000
SizeOfHeapReserve 00000000
SizeOfHeapCommit 00000000
LoaderFlags 00000000
NumberOfRvaAndSizes 00000000
The Data Directory
Entry 0 00000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 00000000 00000000 Import Directory [parts of .idata]
Entry 2 00000000 00000000 Resource Directory [.rsrc]
Entry 3 00000000 00000000 Exception Directory [.pdata]
Entry 4 00000000 00000000 Security Directory
Entry 5 00000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000 00000000 Debug Directory
Entry 7 00000000 00000000 Description Directory
Entry 8 00000000 00000000 Special Directory
Entry 9 00000000 00000000 Thread Storage Directory [.tls]
Entry a 00000000 00000000 Load Configuration Directory
Entry b 00000000 00000000 Bound Import Directory
Entry c 00000000 00000000 Import Address Table Directory
Entry d 00000000 00000000 Delay Import Directory
Entry e 00000000 00000000 CLR Runtime Header
Entry f 00000000 00000000 Reserved
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 000024fb 00000000 00000000 000000c0 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _binary_Lilothyn_jpg_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000024fb _binary_Lilothyn_jpg_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000024fb _binary_Lilothyn_jpg_size
... and the other:
Tommy.o: file format pei-i386
Tommy.o
architecture: i386, flags 0x00000030:
HAS_SYMS, HAS_LOCALS
start address 0x00000000
Characteristics 0x305
relocations stripped
line numbers stripped
32 bit words
debugging information removed
Time/Date Thu Jan 01 00:00:00 1970
Magic 0000
MajorLinkerVersion 0
MinorLinkerVersion 0
SizeOfCode 00000000
SizeOfInitializedData 00000000
SizeOfUninitializedData 00000000
AddressOfEntryPoint 00000000
BaseOfCode 00000000
BaseOfData 00000000
ImageBase 00000000
SectionAlignment 00000000
FileAlignment 00000000
MajorOSystemVersion 0
MinorOSystemVersion 0
MajorImageVersion 0
MinorImageVersion 0
MajorSubsystemVersion 0
MinorSubsystemVersion 0
Win32Version 00000000
SizeOfImage 00000000
SizeOfHeaders 00000000
CheckSum 00000000
Subsystem 00000000 (unspecified)
DllCharacteristics 00000000
SizeOfStackReserve 00000000
SizeOfStackCommit 00000000
SizeOfHeapReserve 00000000
SizeOfHeapCommit 00000000
LoaderFlags 00000000
NumberOfRvaAndSizes 00000000
The Data Directory
Entry 0 00000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 00000000 00000000 Import Directory [parts of .idata]
Entry 2 00000000 00000000 Resource Directory [.rsrc]
Entry 3 00000000 00000000 Exception Directory [.pdata]
Entry 4 00000000 00000000 Security Directory
Entry 5 00000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000 00000000 Debug Directory
Entry 7 00000000 00000000 Description Directory
Entry 8 00000000 00000000 Special Directory
Entry 9 00000000 00000000 Thread Storage Directory [.tls]
Entry a 00000000 00000000 Load Configuration Directory
Entry b 00000000 00000000 Bound Import Directory
Entry c 00000000 00000000 Import Address Table Directory
Entry d 00000000 00000000 Delay Import Directory
Entry e 00000000 00000000 CLR Runtime Header
Entry f 00000000 00000000 Reserved
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 000834fe 00000000 00000000 000000c0 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _binary_Tommy_jpg_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000834fe _binary_Tommy_jpg_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000834fe _binary_Tommy_jpg_size
The problem is that this last file (Tommy.o) loads properly, while the 1st file (Lilothyn.o) doesn't. As you can see the two are seemingly similar.
My code is extensive so i'll post the relevant parts only.
Source.cpp:
int displayFillThread(SDL_Renderer *renderer, SDL_Window *window, bool *_end) throw()
{
std::cout << "Thread initializing..." << std::endl;
SDL_Texture *texture = getTextureFromStream(&binary_Lilothyn_jpg_start, binary_Lilothyn_jpg_size, window, renderer);
if (texture == NULL)
{
std::cout << "Thread: Failed to load image - " << SDL_GetError() << std::endl;
return 1;
}
std::cout << "Thread initialized!" << std::endl;
for(int i= 10; !*_end && i < 400; i+= 100)
for(int j= 10; !*_end && j < 400; j+= 100)
{
SDL_Delay(100);
AddTextureToRederer(renderer, texture, i, j, 100, 100);
SDL_RenderPresent(renderer);
}
return 0;
}
SDL_Texture *getTextureFromStream(char binary[], unsigned int binary_size, SDL_Window *window, SDL_Renderer *renderer) throw()
{
std::cout << "Starting getTextureFromJPEGStream!" << std::endl;
// char* st = loadFileObject(binary_start, binary_end);
SDL_RWops *rw = SDL_RWFromConstMem(binary, binary_size);
std::cout << "rw loaded!" << std::endl;
SDL_Surface *tmpSurf = IMG_Load_RW(rw, 0);
//SDL_Surface *tmpSurf = SDL_CreateRGBSurfaceFrom(Lilothyn_jpg, 123, 102, 24, 96, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
if (tmpSurf != NULL)
{
SDL_Surface *surf = SDL_ConvertSurfaceFormat(tmpSurf, SDL_GetWindowPixelFormat(window), 0);
if (surf != NULL)
{
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf);
std::cout << "tmpSurf loaded!" << std::endl;
return texture;
}//*/
// SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, tmpSurf);
SDL_FreeSurface(tmpSurf);
std::cout << "surf load failed!" << std::endl;
return NULL;
}
std::cout << "tmpSurf load failed!" << std::endl;
return NULL;
}
int main(int argc, char** argv)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
std::cout << "SDL init Error: " << SDL_GetError() << std::endl;
exit(1);
}
SDL_Window *window = SDL_CreateWindow("SDL_Test", 0, 0, _SCREEN_WIDTH_, _SCREEN_HEIGHT_, SDL_WINDOW_OPENGL | SDL_RENDERER_ACCELERATED); // SDL_WINDOW_FULLSCREEN |
if (window == NULL)
{
std::cout << "Window init Error: " << SDL_GetError() << std::endl;
exit(1);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
//SDL_Texture *texture = getTextureFromJPEGStream(binary_Tommy_jpg_start, binary_Tommy_jpg_end, binary_Tommy_jpg_size, window, renderer);
SDL_Texture *texture = getTextureFromStream(&binary_Tommy_jpg_start, binary_Tommy_jpg_size, window, renderer);
//getTextureFromImage("Resources/Tommy.jpg", window, renderer);
if (texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background Texture init error", SDL_GetError(), window);
return 1;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
//AddTextureToRederer(renderer, FTex, 10, 10, 100, 100);
SDL_RenderPresent(renderer);
SDL_Event event;
bool _end = false;
std::cout << "Starting Thread!" << std::endl;
std::thread thread1;
try
{
thread1 = std::thread(displayFillThread, renderer, window, &_end);
std::cout << "Thread loaded!" << std::endl;
}
catch(std::exception& e)
{
std::cout << "Thread load failed: " << e.what() << std::endl;
return 1;
}
std::cout << "main while starting!" << std::endl;
while(!_end)
{
//...
Source.h:
#ifndef SOURCE_H_
#define SOURCE_H_
static int _SCREEN_WIDTH_ = 1024;
static int _SCREEN_HEIGHT_ = 800;
extern char binary_Tommy_jpg_start;
extern unsigned int binary_Tommy_jpg_size;
extern char binary_Lilothyn_jpg_start;
extern unsigned int binary_Lilothyn_jpg_size;
int displayFillThread(SDL_Renderer *renderer, SDL_Window *window, bool *_end) throw();
SDL_Texture *getTextureFromStream(char binary[], unsigned int binary_size, SDL_Window *window, SDL_Renderer *renderer) throw();
//...
And the output:
Starting getTextureFromJPEGStream!
rw loaded!
tmpSurf loaded!
Starting Thread!
Thread loaded!
Thread initializing...
main while starting!
Note that it didn't write the second "getTextureFromJPEGStream!" neither did it appear to have thrown an exception.
It compiles with no problems whatsoever so, is it possible that the Lilothyn.o file is being created corrupted? (I have rebuilt it more than once) And/or maybe the linker isn't linking correctly?
While executing, the program simple stops responding after loading the 1st image, while trying to load the 2nd.
Thank you for the replies.
I've solved this now, the problem was the types used on the .o file.
New code is as follows.
Source.h:
extern uint8_t binary_Lilothyn_jpg_start[];
extern uint8_t binary_Lilothyn_jpg_size[];
Source.cpp
SDL_Texture *getTextureFromStream(uint8_t binary[], uint8_t binary_size[], SDL_Window *window, SDL_Renderer *renderer) throw()
{
size_t converted_size = (size_t)((void *)binary_size);
SDL_Surface *tmpSurf = IMG_Load_RW(SDL_RWFromConstMem(binary, converted_size), 0);
if (tmpSurf != NULL)
{
//...
Thanks to all the viewers, I hope this helps!
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.