I have 2 threads in a process.
One mallocs and writes packets to a global linked list.
The other keeps reading packets from the global linked list, sends them out through a hardware call and then frees the memory.
This piece of code handles a really large number of packets at a high rate.
Everything works fine except for this one isolated case, where the process aborted due to what seems to be a failed malloc.
It is strange because the man page for malloc says that if malloc fails, it just returns NULL. Could there be any other possible failure with a malloc(), that could cause the process to crash as in my case ?
Here is the backtrace from gdb -
#0 0xffffe430 in __kernel_vsyscall ()
No symbol table info available.
#1 0xf757cc10 in raise () from /lib/libc.so.6 No symbol table info available.
#2 0xf757e545 in abort () from /lib/libc.so.6 No symbol table info available.
#3 0xf75b94e5 in __libc_message () from /lib/libc.so.6 No symbol table info available.
#4 0xf75bf3d4 in malloc_printerr () from /lib/libc.so.6 No symbol table info available.
#5 0xf75c1f5a in _int_malloc () from /lib/libc.so.6 No symbol table info available.
#6 0xf75c3dd4 in malloc () from /lib/libc.so.6 No symbol table info available.
#7 0x080a2466 in np_enqueue_packet_to_tx_queue (prio=2, pkt_type=1 '\001', tx_host_handle=162533812, packet_length=40,
pTxData=0x14dfa694 "", dlci=474, vfport=71369178) at ./np_tx.c:173 No locals.
Here is the code of the sender thread, whose malloc fails.
The sender thread mallocs memory (operation protected by mutex) and writes onto the global queue (also protected by mutex).
When the core dump happened, from gdb I can see that the first malloc was successful, and the second one failed and caused the core dump.
void np_enqueue_packet_to_tx_queue(int prio, WP_U8 pkt_type,
WP_handle tx_host_handle,
WP_S32 packet_length, WP_CHAR *pTxData,
WP_U32 dlci, WP_U32 vfport)
{
STRU_TX_QUEUE_NODE *packetToSend;
packetToSend = malloc(sizeof(STRU_TX_QUEUE_NODE));
if (packetToSend == NULL)
{
WDDI_ERR(" Cannot allocate new memory in np_enqueue_packet_to_tx_queue\n");
return;
}
memset(packetToSend, 0, sizeof(STRU_TX_QUEUE_NODE));
packetToSend->packet = (WP_CHAR*)malloc(packet_length);
if (packetToSend->packet == NULL)
{
WDDI_ERR(" Cannot allocate new memory in np_enqueue_packet_to_tx_queue\n");
free(packetToSend);
packetToSend = NULL;
return;
}
memset(packetToSend->packet, 0, packet_length);
packetToSend->pkt_type = pkt_type;
packetToSend->packet_length = packet_length;
memcpy(packetToSend->packet, pTxData, packet_length);
if (pkt_type == PACKET_TYPE_FR)
{
packetToSend->fr_tx_info.tx_host_handle = tx_host_handle;
packetToSend->fr_tx_info.dlci = dlci;
packetToSend->fr_tx_info.vfport = vfport;
}
pthread_mutex_lock(&tx_queue_mutex);
if (prio == PRIO_HIGH)
{
write_packet_to_tx_queue(&high_prio_tx_queue_g, packetToSend);
}
else
{
write_packet_to_tx_queue(&low_prio_tx_queue_g, packetToSend);
}
pthread_mutex_unlock(&tx_queue_mutex);
// wakeup Tx thread
pthread_cond_signal(&tx_queue_cond);
}
Can someone help pointing out what may have happened wrong here ?
And here is the code for the reader thread. It reads some data from the global queue (operation protected by mutex), releases the mutex, does some processing with the data, and then frees the memory of the data (this operation not protected by mutex).
void *tx_thread(void *arg)
{
STRU_TX_QUEUE_NODE *pickedUpPackets[TX_NUM_PACKETS_BUFFERED];
int read_counter, send_counter;
while (1)
{
pthread_mutex_lock(&tx_queue_mutex);
while ((high_prio_tx_queue_g.len == 0) && (low_prio_tx_queue_g.len == 0))
{
pthread_cond_wait(&tx_queue_cond, &tx_queue_mutex);
}
if (high_prio_tx_queue_g.len)
{
for (read_counter = 0; read_counter < TX_NUM_PACKETS_BUFFERED; read_counter++)
{
pickedUpPackets[read_counter] = read_packet_from_tx_queue(&high_prio_tx_queue_g);
if (pickedUpPackets[read_counter] == NULL)
{
break;
}
}
}
else if (low_prio_tx_queue_g.len)
{
for (read_counter = 0; read_counter < TX_NUM_PACKETS_BUFFERED; read_counter++)
{
pickedUpPackets[read_counter] = read_packet_from_tx_queue(&low_prio_tx_queue_g);
if (pickedUpPackets[read_counter] == NULL)
{
break;
}
}
}
pthread_mutex_unlock(&tx_queue_mutex);
for (send_counter = 0; send_counter < read_counter; send_counter++)
{
np_host_send(pickedUpPackets[send_counter]);
}
}
}
void np_host_send(STRU_TX_QUEUE_NODE *packetToSend)
{
if (packetToSend == NULL)
{
return;
}
// some hardware calls
free(packetToSend->packet);
packetToSend->packet = NULL;
free(packetToSend);
packetToSend = NULL;
}
Related
For a few days now i have been trying to clean up memory leaks in my system. But this one memory leak has been bugging me.
Problem: Valgrind is reporting a memory leak:
==28423== 10,988 (2,624 direct, 8,364 indirect) bytes in 82 blocks are definitely lost in loss record 405 of 409
==28423== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28423== by 0x5553780: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4800.1)
==28423== by 0x1B432E56: janus_audiobridge_create_user_secret (janus_audiobridge_room_helper.c:641)
==28423== by 0x1B4250B3: janus_audiobridge_init (janus_audiobridge.c:281)
==28423== by 0x4111BF: main (janus.c:3898)
Heres janus_audiobridge_create_user_secret (janus_audiobridge_room_helper.c:641):
method_user_secret_error_case *janus_audiobridge_create_user_secret(PGconn *conn, janus_audiobridge_user_secret_model *user_secret_model, gboolean insert_in_db) {
JANUS_LOG(LOG_VERB, "Creating user_secret\n");
/* Create the audio bridge secret */
janus_audiobridge_user_secret *user_secret = g_malloc0(sizeof(janus_audiobridge_user_secret));
method_user_secret_error_case *error = g_malloc0(sizeof(method_user_secret_error_case));
if (user_secret_model->user_secret) {
user_secret->user_secret = g_strdup(user_secret_model->user_secret);
} else {
gchar *new_secret = randstring((size_t)100);
user_secret->user_secret = g_strdup(new_secret);
user_secret_model->user_secret = g_strdup(new_secret); // Model is necesarry for saving to database
g_free(new_secret);
}
user_secret->user_ip = g_strdup(user_secret_model->user_ip);
user_secret->created_at = user_secret_model->created_at;
if (insert_in_db) {
// Save to db
int save_err = janus_audiobridge_create_user_secret_db(conn, user_secret_model);
if (save_err == 0) {
JANUS_LOG(LOG_ERR, "Failed to save to database.\n");
g_free(user_secret->user_secret);
g_free(user_secret->user_ip);
g_free(user_secret);
const gchar *error_message = "Error saving to database.\n";
error->error = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
error->error_message = error_message;
return error;
}
}
g_hash_table_insert(user_secrets, g_strdup(user_secret->user_secret), user_secret);
// Prepare response
const gchar *error_message = "";
error->error = 0;
error->error_message = error_message;
error->user_secret = user_secret;
return error;
}
And of course janus_audiobridge_init (janus_audiobridge.c:281):
/* Fetch all user_secrets from database */
const gchar *select_all_user_secrets_query = "SELECT * FROM user_secrets;";
GHashTable *user_secrets_db = user_secrets_query(conn, select_all_user_secrets_query);
// Create user secrets from database
g_hash_table_iter_init(&iter, user_secrets_db);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
janus_audiobridge_user_secret_model *db_user_secret = value;
method_user_secret_error_case *create_resp = janus_audiobridge_create_user_secret(conn, db_user_secret, (gboolean)FALSE);
if (create_resp->error != 0) {
JANUS_LOG(LOG_ERR, "Error: %s\n", create_resp->error_message);
}
g_free(db_user_secret->user_secret);
g_free(db_user_secret->user_ip);
g_free(db_user_secret);
g_free(create_resp);
}
// Free the hashtable of entries from database
g_hash_table_destroy(user_secrets_db);
So my question is following: Why valgrind shows that i am leaking memory even tho, i am freeing it with g_free? The other user_secret struct is stored in HashTable, so i can't free it, because i am using it later.
P.S I don't free user_secret at any place at the code at this time, because i use it consistently in lifetime of my system.
Thanks!
EDIT:
Sorry, i forgot to provide which line is it:
641 line is -
janus_audiobridge_user_secret *user_secret = g_malloc0(sizeof(janus_audiobridge_user_secret));
and 281:
method_user_secret_error_case *create_resp = janus_audiobridge_create_user_secret(conn, db_user_secret, (gboolean)FALSE);
Thanks to #SiggiSv , #n.m and #Attie
After freeing the user secrets on janus_destroy, valgrind stopped reporting that memory leak. So that was more of a problem with me not knowing how valgrind works. Thanks again for everybody who helped.
Here's the code, if somebody finds it usefull:
// Free user secret memory - So Valgrind Doesn't register memory leak
// We do this, because we don't delete user secret in janus logic, and valgrind sees that as a memory leak
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init(&iter, user_secrets);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
janus_audiobridge_user_secret *user_secret = value;
g_free(user_secret->user_secret);
g_free(user_secret->user_ip);
g_free(user_secret);
}
g_hash_table_destroy(user_secrets);
I asked a question earlier about this program and was able to resolve it--the good news is my program is working now! The bad news is that it only works when I run it through gdb. Whenever I normally compile the program it'll crash, but running it through gdb gives correct output and allows it to exit normally.
I read Dennis Yurichev's post on debugging this sort of problem with the stack or something in gdb, but I'm still pretty new to programming so I have no idea what I am doing.
Here is the output from attaching gdb to the process ID of the program and then dumping the stack:
Breakpoint 1, 0x74337480 in OutputDebugStringA () from C:\WINDOWS\SysWOW64\KernelBase.dll
(gdb) bt
#0 0x74337480 in OutputDebugStringA () from C:\WINDOWS\SysWOW64\KernelBase.dll
#1 0x77478a64 in msvcrt!_invalid_parameter () from C:\WINDOWS\SysWOW64\msvcrt.dll
#2 0x77425a20 in wctype () from C:\WINDOWS\SysWOW64\msvcrt.dll
#3 0x00010001 in ?? ()
#4 0x77493a09 in msvcrt!fscanf_s () from C:\WINDOWS\SysWOW64\msvcrt.dll
#5 0x7749399b in msvcrt!fscanf () from C:\WINDOWS\SysWOW64\msvcrt.dll
#6 0x00401d0d in main () at ZigSort.c:377
I think it's saying it's crashing due to invalid input or something from fscanf, but that doesn't make sense...
The line referenced (main() line 377) is the first fscanf in here:
int main(void)
{
//initializing file pointer
FILE * ifp;
ifp = fopen("zigzag.txt", "r");
int n;
//getting number of values
fscanf(ifp, "%d", &n); //**LINE 377 RIGHT HERE**
//reading values into a queue
queue_t * data = queue_create();
int ipt;
for(int i=0; i<n; i++)
{
fscanf(ifp, "%d", &ipt);
queue_enqueue(data, ipt);
}
//creating a stack of queues
run_stack_t * runstack = run_stack_create();
queue_t * run = queue_create();
//finding runs and pushing them onto the stack
int runs = 0;
int *runpoint = &runs;
while(queue_is_empty(data) != 1)
{
run = extract_next_run(data);
run_stack_push(runstack, run);
*runpoint += 1;
optimizestack(runstack, runpoint);
}
//merging queues together in sorted order
data = run_stack_pop(runstack);
queue_t * merger;
runs -= 1;
for(int i=0; i<runs; i++)
{
merger = run_stack_pop(runstack);
data = merge(merger, data);
}
queue_destroy(merger);
//output
printqueue(data);
//freeing memory
queue_destroy(data);
//run_stack_destroy(runstack, runpoint);
free(runstack);
free(runpoint);
fclose(ifp);
}
and the zigzag.txt file that is read in is here:
10
9 8 7 6 8 4 2 3 2 1
I'm happy to try anything or include any other information that may be necessary, I'm just not sure how to solve this problem.
Thanks in advance!
I'm getting a segfault when using libCURL in my HTTP flooder that I wrote for load-testing my site.
Here is the relevant code: https://gist.github.com/AppleDash/a26e0ce0b138cd9eacd2 (A bit large to paste here.)
Here's a link to the line it is segfaulting on: https://gist.github.com/AppleDash/a26e0ce0b138cd9eacd2#file-httpflood-improved-c-L57
And here is a backtrace of the segfault:
#0 0x00007ffff760d65b in fwrite () from /usr/lib/libc.so.6
#1 0x00007ffff79656d8 in ?? () from /usr/lib/libcurl.so.4
#2 0x00007ffff797a76b in ?? () from /usr/lib/libcurl.so.4
#3 0x00007ffff7984349 in ?? () from /usr/lib/libcurl.so.4
#4 0x00007ffff7984b11 in curl_multi_perform () from /usr/lib/libcurl.so.4
#5 0x00007ffff797b977 in curl_easy_perform () from /usr/lib/libcurl.so.4
#6 0x0000000000400f42 in flood (structPointer=0x7fffffffe060) at httpflood.c:57
#7 0x00007ffff7bc5124 in start_thread () from /usr/lib/libpthread.so.0
#8 0x00007ffff768b4bd in clone () from /usr/lib/libc.so.6
I don't see why this call would cause a segfault. Any ideas?
I know you're meant to only provide a small sample of relevant code, but here I am providing the whole thing due to the fact that I feel like context is needed here. (The fact it is being run from many threads and such.)
This is your problem:
for (i = 0; i < threadnum; i++) {
struct flood_data ddosData;
memset(&ddosData, 0, sizeof(struct flood_data));
ddosData.url = url;
ddosData.proxy = getProxy();
pthread_create(&threads[i], NULL, flood, (void *)&ddosData);
}
You're allocating a single struct flood_data instance on the stack and passing that to all of the new threads simultaneously. Each time you iterate through the loop, you overwrite the same instance at the same time that threads spawned from earlier iterations might be trying to read from it. Major undefined behavior.
The proper way to do this is to dynamically allocate a separate instance for each thread:
for (i = 0; i < threadnum; i++) {
struct flood_data *ddosData = calloc(1, sizeof(*ddosData));
ddosData->url = url;
ddosData->proxy = getProxy();
pthread_create(&threads[i], NULL, flood, ddosData);
}
...
void *flood(void *structPointer) {
struct flood_data *data = structPointer;
char *bootable = data->url;
char *proxy = data->proxy;
free(data);
...
}
As pointed out in the comments, you also need to check your system calls for failure. You should validate that all of your calls to fopen() are succeeding, as you could very well be hitting the maximum number of file descriptors open in your process. Rather than opening up a file to /dev/null, why don't you just set a no-op write function with the CURLOPT_WRITEFUNCTION option?
static size_t noop_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
// Do nothing
return size * nmemb;
}
...
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &noop_write_callback);
// No need to call fopen("/dev/null") or set CURLOPT_WRITEDATA now
I was testing out libspotify library (version 12.1.51 x86 for linux) and the application keeps crashing when I call sp_session_create() with a segmentation fault.
I don't have application key, nor a Premium Spotify account (yet), but that shouldn't be the reason for the crash, since if I remember correctly, there is an error code for invalid application key.
My code is as follows:
static uint_8_t g_appkey[] = {1, 2, 3};
static const char *username = "MyUsername";
static const char *password = "MyPassword";
static int logged_in;
static sp_session_callbacks session_callbacks;
static sp_session_config spconfig;
static void on_login(sp_session *session, sp_error error) {
printf("Callback: on_login");
if (error != SP_ERROR_OK) {
printf("Error: Unable to login: %d\n", (int) error);
exit(-1);
}
logged_in = 1;
}
static void on_main_thread_notified(sp_session *session) {
printf("callback: on_main_thread_notified");
}
static void on_log_message(sp_session *session, const char *data) {
printf("callback: on_log_message");
}
int main(int argc, char **argv) {
sp_error error;
sp_session *session;
int next_timeout;
/* struct fill */
memset(&session_callbacks, 0, sizeof(session_callbacks));
memset(&spconfig, 0, sizeof(spconfig));
session_callbacks.logged_in = &on_login;
session_callbacks.notify_main_thread = &on_main_thread_notified;
session_callbacks.log_message = &on_log_message;
spconfig.api_version = SPOTIFY_API_VERSION;
spconfig.cache_location = "tmp";
spconfig.settings_location = "tmp";
spconfig.application_key = g_appkey;
spconfig.application_key_size = sizeof(g_appkey);
spconfig.user_agent = "spot";
spconfig.callbacks = &session_callbacks;
/* session creation */
error = sp_session_create(&spconfig, &session);
if (error != SP_ERROR_OK) {
printf("ERROR: Unable to create spotify session: %s\n", sp_error_message(error));
exit(-1);
}
/* log in */
logged_in = 0;
sp_session_login(session, username, password, 0, NULL);
while(!logged_in) {
sp_session_process_events(session, &next_timeout);
sleep(next_timeout);
}
printf("Sucess!!");
exit(0);
}
Any tips for where could be the problem?
Appreciated for any help given.
backtrace from gdb:
[Thread debugging using libthread_db enabled]
[New Thread 0xb7fe6b70 (LWP 1839)]
[New Thread 0xb7f65b70 (LWP 1840)]
Program received signal SIGSEGV, Segmentation fault.
0x002b9b36 in sp_session_create () from /usr/local/lib/libspotify.so.12
(gdb) thread apply all backtrace
Thread 3 (Thread 0xb7f65b70 (LWP 1840)):
#0 0x0012d422 in __kernel_vsyscall ()
#1 0x003e6ce6 in nanosleep () at ../sysdeps/unix/syscall-template.S:82
#2 0x0041644c in usleep (useconds=10000) at ../sysdeps/unix/sysv/linux/usleep.c:33
#3 0x00293581 in ?? () from /usr/local/lib/libspotify.so.12
#4 0x00293990 in ?? () from /usr/local/lib/libspotify.so.12
#5 0x001d42b7 in ?? () from /usr/local/lib/libspotify.so.12
#6 0x004ae96e in start_thread (arg=0xb7f65b70) at pthread_create.c:300
#7 0x0041ca4e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130
Thread 2 (Thread 0xb7fe6b70 (LWP 1839)):
#0 0x0012d422 in __kernel_vsyscall ()
#1 0x004b5245 in sem_wait##GLIBC_2.1 () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/sem_wait.S:80
#2 0x002178fa in ?? () from /usr/local/lib/libspotify.so.12
#3 0x001d42b7 in ?? () from /usr/local/lib/libspotify.so.12
#4 0x004ae96e in start_thread (arg=0xb7fe6b70) at pthread_create.c:300
#5 0x0041ca4e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130
Thread 1 (Thread 0xb7fe78d0 (LWP 1836)):
#0 0x002b9b36 in sp_session_create () from /usr/local/lib/libspotify.so.12
#1 0x080487d5 in main ()
(gdb)
Problem solved.
I got a valid application key from spotify, tested out my code and now it works.
It seems that the current live libspotify version has a bug when entering invalid application keys.
variables with storage class static do not need to be nullified, they are by default
/* struct fill */
memset(&session_callbacks, 0, sizeof(session_callbacks));
memset(&spconfig, 0, sizeof(spconfig));
Make sure these folders actually exist
EDIT: Actually cache_location should be created by the lib.
spconfig.cache_location = "tmp";
spconfig.settings_location = "tmp";
For a complete example see:
http://damienradtke.org/playing-with-the-spotify-api/
Your fake app-key is very short. Looking at a valid app-key, it's 321 bytes long and the first two bytes are the big-endian number 322. I'd guess that perhaps those first two bytes tell libspotify how big a null-terminated string it needs to allocate to store the whole key. If libspotify trusts that instead of application_key_size, that might be why it's crashing instead of returning an error.
I took this code and built it against libspotify-12, and got it to execute with the expected error about app ID:
libspotify/examples/jukebox$ make
cc -I/usr/include/alsa -I/home/nik/Code/spotify/libspotify/targets/Linux-x86_64-release/include -Wall -Wl,-rpath,/home/nik/Code/spotify/libspotify/targets/Linux-x86_64-release/lib -L/home/nik/Code/spotify/libspotify/targets/Linux-x86_64-release/lib jukebox.o appkey.o alsa-audio.o audio.o -o jukebox -lasound -lpthread -lspotify
libspotify/examples/jukebox$ ./jukebox
ERROR: Unable to create spotify session: Invalid application key
If you're having trouble getting things up and running, I would encourage you to take a look at the example code which ships with libspotify, specifically the jukebox example. In the above shell example, I just replaced jukebox.c with your code and got it to build with no problems.
It is possible that there is some bug here which was fixed in a later version of libspotify (disclaimer: I work for Spotify and actually compiled the above example with the latest 12.x code, which may contain some unreleased bugfixes). However, the code itself doesn't seem to do anything out of the ordinary, but again, if you're having problems I would suggest adapting jukebox.c to your purposes.
I have a tree structure which I am adding a large amount of nodes too. The number of times this is done (tree cleaned between runs) and the number of nodes is given as a command line argument. For numbers of nodes roughly < 6000 and any number of runs the program performs as expected. However when the number of nodes exceeds this and the number of runs exceeds a low number around 50 the program causes a segmentation fault.
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff7201740 <main_arena>, bytes=112) at malloc.c:3570
3570 malloc.c: No such file or directory.
Using backtrace this tracks too
#0 _int_malloc (av=0x7ffff7201740 <main_arena>, bytes=112) at malloc.c:3570
#1 0x00007ffff6ecbfb5 in __GI___libc_malloc (bytes=112) at malloc.c:2924
#2 0x0000000000401a99 in createTreeForQuad (quad=...) at cs257.c:217
#3 0x0000000000401b3a in addQuadsToTree (tree=tree#entry=0x2f965c8) at cs257.c:230
#4 0x0000000000401dec in addBody (tree=tree#entry=0x2f965c8, body=...) at cs257.c:292
#5 0x0000000000402146 in addBodyToCorrectQuad (body=..., tree=tree#entry=0x2f961c8) at cs257.c:245
#6 0x0000000000401eaf in addBody (tree=tree#entry=0x2f961c8, body=...) at cs257.c:296
#7 0x0000000000402146 in addBodyToCorrectQuad (body=..., tree=tree#entry=0x2f95dc8) at cs257.c:245
Note that the addBody -> addBodyToCorrectQuad -> addBody recursion happens a large number of times at high number of nodes. The code with the malloc which fails is below.
Tree *createTreeForQuad(Quad quad) {
Tree *tree;
tree = (Tree *)malloc(sizeof*tree);
if (tree != NULL){
tree->quad = quad;
tree->internal = 0;
tree->bodyEmpty = 1;
return tree;
}else{
printf("\n ------------------------------------ MALLOC FAILED----------------------------------------");
}
}
The code I use to free the tree is as follows, with it being called on the root node and the internal flag being set to 0 when the tree is a leaf.
void cleanTree(Tree **tree) {
if((*tree)->internal == 0) {
free(*tree);
}
else{
cleanTree(&((*tree)->NE));
cleanTree(&((*tree)->SE));
cleanTree(&((*tree)->SW));
cleanTree(&((*tree)->NW));
cleanTree(&((*tree)->NE1));
cleanTree(&((*tree)->NW1));
cleanTree(&((*tree)->SE1));
cleanTree(&((*tree)->SW1));
free(*tree);
}
}
The tree struct looks like this
typedef struct Tree Tree;
struct Tree {
Body body;
Quad quad;
Tree *NE;
Tree *NW;
Tree *SE;
Tree *SW;
Tree *NE1;
Tree *NW1;
Tree *SE1;
Tree *SW1;
int internal;
int bodyEmpty;
};
The code for adding Bodys to the tree is as follows with addBodyToCorrectQuad calling addBody on the quad that the body exists within.
void addBody(Tree **tree, Body body) {
if( (*tree)->bodyEmpty == 1) {
(*tree)->body = body;
(*tree)->bodyEmpty = 0;
}
else {
if((*tree)->internal) {
(*tree)->body = combineBody((*tree)->body, body);
addBodyToCorrectQuad(body, tree);
//printf("B\n");
}
else{
(*tree)->internal = 1; /
addQuadsToTree(tree);
//printf("%f",((*tree)->NW)->quad.x);
addBodyToCorrectQuad((*tree)->body, tree);
(*tree)->body = combineBody((*tree)->body, body);
addBodyToCorrectQuad(body, tree);
//printf("C\n");
}
}
}
You have heap corruption somewhere -- someone is running off the end of an array or dereferencing an invalid pointer or using some object after it has been freed.
Try using valgrind or some other memory debugging tool to narrow down where the problem is.