Contents of array changing within a struct in C - c

I'm currently stumped on this problem I have.
I have this structure:
typedef struct corgi_entry {
unsigned pup; //Supposed to be hex
} corgi_entry, *Pcorgi_entry;
typedef struct corgi {
Pcorgi_entry *arrayCorgiHead;
} corgi, *Pcorgi;
I have this variables:
static corgi c1;
In an init function, I malloc my arrayCorgiHead
c1.arrayCorgiHead = (Pcorgi_entry *)malloc(sizeof(Pcorgi_entry) * corgiNumber));
The corgiNumber is just a placeholder, it can be however many, just the size of the index.
Given this, later on I'm running a loop. Every iteration of the loop, I'm given a corgi and an index from somewhere. If at that index it is null, I'm supposed to make a corgi and assign the pup data to be the same. If it's not null, I check the corgi I'm given with the corgi at the index to see if the pup match.
if(c1.arrayCorgiHead[index] == NULL){
corgi_entry newcorgi_entry = {pupnumber};
c1.arrayCorgiHead[index] = &newcorgi_entry;
printf("Corgi Made!, pup: %10x\n", c1.arrayCorgiHead[index]->pup); //For debug purposes
}
else{ //Not null
if(c1.arrayCorgiHead[index]->pup != given_corgi_pup){
printf("Corgi Found?, pup: %10x\n", c1.arrayCorgiHead[index]->pup); //For debug purposes
//Do stuff
}
}
Here's the problem. In the file where I give this code the "external" index/corgis, on my third entry I give it the same as the first:
Index: 1 Corgi{pup = 123}
Index: 2 Corgi{pup = 456}
Index: 1 Corgi{pup = 123}
For some reason, when it processes the third entry, it says that it doesn't match. I print out the corgi pup at the array index, and I get some really weird number that doesn't make any sense (9814008 or something). This random number changes every time I ./corgisim and whatnot.
I do not touch the array at any other point besides what's written here. Why would my data be changing after a loop iteration?
*edit: To clarify my last point, my printf statements goes
Corgi Made!, pup: 123
Corgi Made!, pup: 456
Corgi Found?, pup: 20138940139 (random number that changes every time I run my program)
This code has been abbreviated for the sake of clarity (and corgi-ed, I don't know if that makes things clearer or not. The numbness in my brain has driven me insane). As you may be able to tell from the code, I'm not very familiar with C.
Thanks!
Edit 2: Thanks guys, solution worked like a charm! Pretty long question for a pretty simple problem, but I'm glad I figured it out. Much appreciated.

Here is the problem:
corgi_entry newcorgi_entry = {pupnumber};
c1.arrayCorgiHead[index] = &newcorgi_entry;
Variable newcorgi_entry is a local variable, which is allocated on the stack. Therefore, once outside the variable's scope of declaration, you cannot rely on &newcorgi_entry as a valid memory address.
Here is the solution:
You should allocate the corgi_entry instance on the heap instead:
corgi_entry* newcorgi_entry = malloc(sizeof(corgi_entry));
newcorgi_entry->pup = pupnumber;
c1.arrayCorgiHead[index] = newcorgi_entry;

The problem is how you "allocate" memory:
corgi_entry newcorgi_entry = {pupnumber};
c1.arrayCorgiHead[index] = &newcorgi_entry;
Here, newcorgi_entry is allocated on the stack. Then you assign the address of that stack variable to your array. Problem is, as soon as your function runs out of scope that memory is free to be used by any other function and sooner or later gets overwritten by some other code.
There are two solutions: either allocate on the heap using malloc, or don't use pointers at all. The first solution looks like this:
Pcorgi_entry newcorgi_entry = malloc(sizeof(corgi_entry));
newcorgi_entry->pub = pubnumber;
c1.arrayCorgiHead[index] = newcorgi_entry;
For the second solution there are a few variations. Here's one:
typedef struct corgi_entry {
unsigned pup;
int inUse;
} corgi_entry, *Pcorgi_entry;
typedef struct corgi {
corgi_entry *arrayCorgiHead; // "Head" is the wrong name here, IMHO.
} corgi, *Pcorgi;
static corgi c1;
// calloc clears the memory to 0
c1.arrayCorgiHead = (corgi_entry *)calloc(corgiNumber, sizeof(corgi_entry));
if(!c1.arrayCorgiHead[index].inUse){
c1.arrayCorgiHead[index].pub = pubNumber
c1.arrayCorgiHead[index].inUse = 1;
printf("Corgi Made!, pup: %10x\n", c1.arrayCorgiHead[index].pup); //For debug purposes
}
else{
if(c1.arrayCorgiHead[index].pup != given_corgi_pup){
printf("Corgi Found?, pup: %10x\n", c1.arrayCorgiHead[index].pup); //For debug purposes
//Do stuff
}
}
I think the corgi struct and its variable are unnecessary. I'd do it like this instead:
typedef struct corgi_entry {
unsigned pup;
int inUse;
} corgi_entry;
static corgi_entry *corgis;
// calloc clears the memory to 0
corgis = (corgi_entry *)calloc(corgiNumber, sizeof(corgi_entry));
if(!corgis[index].inUse){
corgis[index].pub = pubNumber
corgis[index].inUse = 1;
printf("Corgi Made!, pup: %10x\n", corgis[index].pup); //For debug purposes
}
else{
if(corgis[index].pup != given_corgi_pup){
printf("Corgi Found?, pup: %10x\n", corgis[index].pup); //For debug purposes
//Do stuff
}
}
Yet another way would be if you define the "pubNumber" 0 to be illegal so you can us it as a sentinel instead:
typedef struct corgi_entry {
unsigned pup;
} corgi_entry;
static corgi_entry *corgis;
// calloc clears the memory to 0
corgis = (corgi_entry *)calloc(corgiNumber, sizeof(corgi_entry));
// pub number 0 is illegal, so it must be an unused entry
if(corgis[index].pub == 0) {
corgis[index].pub = pubNumber
printf("Corgi Made!, pup: %10x\n", corgis[index].pup); //For debug purposes
}
else{
if(corgis[index].pup != given_corgi_pup){
printf("Corgi Found?, pup: %10x\n", corgis[index].pup); //For debug purposes
//Do stuff
}
}

Related

Alias for variable of type struct in C

I would like to create (some type of) "alias" to a struct object in C.
Based on a variable, a should be x or y. But it should not be copied, it needs to be a reference to that a-object.
Some code:
void search(node start, node end) {
int myid = omp_get_thread_num();
node localstart;
if (myid == 0) {
// start correct way
localstart = start; // <-- how?!
}
else{
// start reversed way
localstart = end; // <-- how?!
}
// do something with localstart eg.:
localstart->dist = 0;
// now should
// start->dist == 0 or end->dist == 0 (based on myid)
// be true!
}
The code is some part of a bidirectional search. One thread should start at the start and search for the end and the other one should start at the end and search for the start.
On the other hand, I could call a function with start and end (and reversed). But also here, I would need to pass the struct as reference.
I would like to use the first idea, if possible!
In C, you reference a variable using a pointer:
node *localstart;
if (myid == 0) {
// start correct way
localstart = &start;
}
else {
// start reversed way
localstart = &end;
}
(*localstart)->dist = 0;
From your usage of node it is clear that it is actually a pointer to a structure, so now you have a pointer-to-pointer. Not a problem for the C compiler, it can even optimize away the pointer variable in some cases. Just do not forget the parentheses!

Allocating memory for struct within a struct in cycle

I'm working on INI-style configuration parser for some project, and I gets next trouble.
I have 3 structures:
typedef struct {
const char* name;
unsigned tract;
int channel;
const char* imitation_type;
} module_config;
typedef struct {
int channel_number;
int isWorking;
int frequency;
int moduleCount;
} channel_config;
typedef struct {
int mode;
module_config* module;
channel_config* channel;
} settings;
And I have function for handling data in my INI-file (I working under inih parser): [pasted to pastebin cause too long]. Finally, in main(), I did the next:
settings* main_settings;
main_settings = (settings*)malloc(sizeof(settings));
main_settings->module = (module_config*)malloc(sizeof(module_config));
main_settings->channel = (channel_config*)malloc(sizeof(channel_config));
if (ini_parse("test.ini", handler, &main_settings) < 0) {
printf("Can't load 'test.ini'\n");
return 1;
}
In result, binary crashes with memory fault. I think (no, I KNOW), what I'm incorrectly allocating the memory in handler(), but I does not understand, where I do it wrong. I spent all night long trying to understand memory allocating, and I'm very tired, but now me simply interestingly, what I'm doing wrong, and HOW to force this working fine.
P.S. Sorry for ugly english
The problem seems to be related to the reallocation of your structs:
pconfig = (settings *) realloc(pconfig, (module_count + channel_count) * sizeof(channel_config));
pconfig->module = (module_config *) realloc(pconfig->module, module_count * sizeof(module_config));
pconfig->channel = (channel_config *) realloc(pconfig->channel, channel_count * sizeof(channel_config));
First of all, you must not reallocate the main settings struct. Since your handler will always be called with the original pconfig value, the reallocation of the module and channel arrays has no effect, and you'll access freed memory.
Also when reallocating the module and channel arrays you should allocate count + 1 elements, since the next invocation of handler might assign to the [count] slot.
So try to replace the three lines above with:
pconfig->module = (module_config *) realloc(pconfig->module, (module_count + 1) * sizeof(module_config));
pconfig->channel = (channel_config *) realloc(pconfig->channel, (channel_count + 1) * sizeof(channel_config));

Timing behavior of null pointers in C

The below is mostly tested for Microsoft CL Version 17.00.50727.1 on Windows 7, but I see something similar with g++. I'm quite sure that the logical function is correct. The question is only about the timing.
Essentially I have a function that dynamically returns new "blocks" of data as needed. If it runs out of space in its "page", it makes a new page.
The purpose of the blocks is to match incoming data keys. If the key is found, that's great. If not, then a new data key is added to the block. If the block runs out of space, then a new block is created and linked to the old one.
The code works whether or not the block-making function explicitly sets the "next" pointer in the new block to NULL. The theory is that calloc() has set the content to 0 already.
The first odd thing is that the block-making function takes about 5 times(!) longer to run when that "next" pointer is explicitly set to NULL. However, then that is done, then the timing of the overall example behaves as expected: It takes linearly longer to match a new key, the more entries there are in the key list. The only difference occurs when a key is added which causes a new block to be fetched. The overhead of doing that is similar to the time taken to call the block-making function.
The only problem with this is that the block-making function is unacceptably slow then.
When the pointer is NOT explicitly set to NULL, then the block-making function becomes nice and fast -- maybe half to a quarter of the key-matching function, instead of as long or even longer.
But then the key-matching function starts to exhibit odd timing behavior. It does mostly increase linearly with the number of keys. It still has jumps at 16 and 32 keys (since the list length is 16). But it also has a large jump at key number 0, and it has large jumps at keys number 17, 33 etc.
These are the key numbers when the program first has to look at the "next" pointer. Apparently it takes a long time to figure out that the 0 value from calloc is really a NULL pointer? Once it knows this, the next times are faster.
The second weird thing is that the effect goes away if the data struct consists exclusively of the key. Now the jumps at 0, 17, 33 etc. go away whether or not the "next" pointer is explicitly set to NULL. But when "int unused[4]" is also in the struct, then the effect returns.
Maybe the compiler (with option /O2 or with -O3 for g++) optimizes away the struct when it consists of a single number? But I still don't see why that would affect the timing behavior in this way.
I've tried to simplify the example as much as I could from the real code, but I'm sorry that it's still quite long. It's not that complicated, though.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
void timer_start(int n);
void timer_end(int n);
void print_times();
// There are pages of blocks, and data entries per block.
// We don't know ahead of time how many there will be.
// GetNextBlock() returns new blocks, and if necessary
// makes new pages. MatchOrStore() goes through data in
// a block to try to match the key. It won't ever match
// in this example, so the function makes a new data entry.
struct dataType
{
// Surprise number 1: If the line with "unused" is
// commented out, things behave as expected, even if
// Surprise number 2 is in effect.
int unused[4];
int key;
};
#define DATA_PER_BLOCK 16
struct blockType
{
char nextEntryNo;
struct dataType list[DATA_PER_BLOCK];
struct blockType * next;
};
struct pageType
{
int nextBlockNo;
struct blockType * list;
struct pageType * next;
struct pageType * prev;
};
struct blockType * GetNextBlock();
void MatchOrStore(
struct dataType * dp,
struct blockType * bp);
struct pageType * pagep;
int main(int argc, char * argv[])
{
pagep = (struct pageType *) 0;
struct dataType data;
for (int j = 0; j < 50000; j++)
{
struct blockType * blockp = GetNextBlock();
// Make different keys each time.
for (data.key = 0; data.key < 40; data.key++)
{
// One timer per key number, useful for statistics.
timer_start(data.key);
MatchOrStore(&data, blockp);
timer_end(data.key);
}
}
print_times();
exit(0);
}
#define BLOCKS_PER_PAGE 5000
struct blockType * GetNextBlock()
{
if (pagep == NULL ||
pagep->nextBlockNo == BLOCKS_PER_PAGE)
{
// If this runs out of page space, it makes some more.
struct pageType * newpagep = (struct pageType *)
calloc(1, sizeof(struct pageType));
newpagep->list = (struct blockType *)
calloc(BLOCKS_PER_PAGE, sizeof(struct blockType));
// I never actually free this, but you get the idea.
newpagep->nextBlockNo = 0;
newpagep->next = NULL;
newpagep->prev = pagep;
if (pagep)
pagep->next = newpagep;
pagep = newpagep;
}
struct blockType * bp = &pagep->list[ pagep->nextBlockNo++ ];
// Surprise number 2: If this line is active, then the
// timing behaves as expected. If it is commented out,
// then presumably calloc still sets next to NULL.
// But the timing changes in an unexpected way.
// bp->next = (struct blockType *) 0;
return bp;
}
void MatchOrStore(
struct dataType * dp,
struct blockType * blockp)
{
struct blockType * bp = blockp;
while (1)
{
for (int i = 0; i < bp->nextEntryNo; i++)
{
// This will spend some time traversing the list of
// blocks, failing to find the key, because that's
// the way I've set up the data for this example.
if (bp->list[i].key != dp->key) continue;
// It will never match.
return;
}
if (! bp->next) break;
bp = bp->next;
}
if (bp->nextEntryNo == DATA_PER_BLOCK)
{
// Once in a while it will run out of space, so it
// will make a new block and add it to the list.
timer_start(99);
struct blockType * bptemp = GetNextBlock();
bp->next = bptemp;
bp = bptemp;
timer_end(99);
}
// Since it didn't find the key, it will store the key
// in the list here.
bp->list[ bp->nextEntryNo++ ].key = dp->key;
}
#define NUM_TIMERS 100
#ifdef _WIN32
#include <time.h>
LARGE_INTEGER
tu0[NUM_TIMERS],
tu1[NUM_TIMERS];
#else
#include <sys/time.h>
struct timeval
tu0[NUM_TIMERS],
tu1[NUM_TIMERS];
#endif
int ctu[NUM_TIMERS],
number[NUM_TIMERS];
void timer_start(int no)
{
number[no]++;
#ifdef _WIN32
QueryPerformanceCounter(&tu0[no]);
#else
gettimeofday(&tu0[no], NULL);
#endif
}
void timer_end(int no)
{
#ifdef _WIN32
QueryPerformanceCounter(&tu1[no]);
ctu[no] += (tu1[no].QuadPart - tu0[no].QuadPart);
#else
gettimeofday(&tu1[no], NULL);
ctu[no] += 1000000 * (tu1[no].tv_sec - tu0[no].tv_sec )
+ (tu1[no].tv_usec - tu0[no].tv_usec);
#endif
}
void print_times()
{
printf("%5s %10s %10s %8s\n",
"n", "Number", "User ticks", "Avg");
for (int n = 0; n < NUM_TIMERS; n++)
{
if (number[n] == 0)
continue;
printf("%5d %10d %10d %8.2f\n",
n,
number[n],
ctu[n],
ctu[n] / (double) number[n]);
}
}

Malloc Typedef Struct Problems

I am working on building a threads library and for some reason have run into a simple malloc problem that I can't fix right now. I'm sure it's something simple I'm just missing it.
In my main.c I have the following code:
//declare testSem
tasem_t testSem;
int main(int argc, char **argv){
ta_libinit();
//initialize testSem
ta_sem_init(&testSem, 5);
//wait test
ta_sem_wait(&testSem);
the relevant code in my thread library is as follows:
void ta_sem_init(tasem_t *sema, int value)
{
//malloc the semaphore struct
sema = malloc(sizeof(tasem_t));
//error check
if(sema == NULL)
{
printf("could not malloc semaphore");
exit(0);
}
//initialize with the given value
sema->val = value;
printf("SemaVal = %i\n", sema->val);
}
void ta_sem_wait(tasem_t *sema)
{
printf("SemaVal = %i\n", sema->val);
if(sema->val <= 0)
{
//not done yet
printf("SWAPPING\n");
}
else
{
printf("SemaVal = %i\n", sema->val);
sema->val = sema->val + 1;
}
}
Here is the struct from my header file:
//struct to store each semas info
typedef struct tasem_t_struct
{
//value
int val;
//Q* Queue
//int numThreads
}tasem_t;
The output I get from this is:
SemaVal = 5
SemaVal = 0
SWAPPING
So evidently, I'm not mallocing my struct correctly as the value inside is lost once I go out of scope. I know I must just be forgetting something simple. Any ideas?
You can't seem to decide who's responsible for allocating your tasem_t structure. You have a global variable for it and pass its address to ta_sem_init. But then you have ta_sem_init dynamically allocate a brand new tasem_t structure, saving its address to sema, a local function argument, so that address gets lost when it falls out of scope.
Pick one, either:
Make ta_sem_init initialize an existing tasem_t variable.
Make ta_sem_init allocate and initialize a new tasem_t structure and then return its address (either directly or via a tasem_t** output parameter).

Setting struct variables - C

I have some code in the following kind of layout, I believe that the topExample/botExample aren't being set properly when I call addTopBotExample. I think this is due to the top bot variables being on the functions stack and so being cleared when the function ends? I have a feeling that perhaps I need to malloc the memory first, but am not sure how I would go about doing this are even if its the right approach.
typedef struct Example Example;
struct Example {
/* normal variables ...*/
Example *topExample;
Example *botExample;
};
....
void addTopBotExample(Example **example, int someVariable) {
Example top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example bot = createBotExample(int someVariable);
(*example)->topExample = &top;
(*example)->botExample = &bot;
return;
}
If createTopExample isn't allocating memory, this is going to cause problems the moment it's called more than once. Rewrite createTopExample and createBotExample to use malloc and return an Example*. Something like this:
Example* createTopExample(stuff)
{
Example *example = malloc(sizeof(Example));
// ... stuff you do
return example;
}
Then your addTopBotExample would look like this:
void addTopBotExample(Example **example, int someVariable) {
if ((*example)->topExample)
free((*example)->topExample)
if ((*example)->botExample)
free((*example)->botExample)
(*example)->topExample = createTopExample(int someVariable);
(*example)->botExample = createBotExample(int someVariable);
return;
}
Note that this addTopBotExample will free the allocated memory before calling malloc again but before your program ends, you need to call free on any lingering Examples that used this addTopBotExample function:
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.topExample);
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.botExample);
You have already everything together. Allocate the Example in createTopExample or createTopExample
Example *createTopExample(int someVariable)
{
Example *x = malloc(sizeof(Example));
/* initialize x */
return x;
}
and in addTopBotExample
void addTopBotExample(Example *example, int someVariable) {
Example *top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example *bot = createBotExample(int someVariable);
example->topExample = top;
example->botExample = bot;
return;
}
Ooooo, this is bad. The expression "Example top" in the addTopBotExample() function allocated that object on the stack. It'll be trashed after exiting from the function. (Same for "Example bot" on the following line.) Something like this will work better:
void addTopBotExample(Example **example, int someVariable) {
Example *top = createTopExample(someVariable); // NOTE THE *
Example *bot = createBotExample(someVariable); // NOTE THE *
(*example)->topExample = top; // NOT &top !!
(*example)->botExample = bot; // NOT &bot !!
return;
}
And you'll want to write createTopExample and createBotExample so they return pointers:
#include <stdlib.h> // For malloc!
Example *createTopExample(stuff) // Note *. It's returning a pointer.
{
Example *example = malloc(sizeof(Example)); // Allocate on the HEAP. Lives after this function call.
// Fill in the fields of example.
example->field1 = 25; // Note the "->": you're dereferencing a pointer.
example->title = "Example title";
return example;
}

Resources