I've discovered a segfault that I'm having trouble parsing. Lest you think I haven't searched, I don't think the issue is the same as in this question. I have the following typedef'd structure:
typedef struct usage usage;
struct usage{
char name[9];
int loc;
usage *next;
};
I'm reading data from a file that consists of a number K followed by K pairs (S,D) where S= an 8-character string [this is a variable name] and d= an integer [a memory location].
Here's the code that's causing the error:
void addUse(int index,char *nm, int addr){
usage *temp;
strcpy(temp->name,nm); //segfault here.
temp->loc = addr;
temp->next= NULL;
/* more processing */
}
To make this clearer, I am calling this function from a block where I have
int dummyIndex = 1;
char s1[9];
int val1;
scanf(" %s %d, s1, &val1);
addUse(dummyIndex, s1, val1);
It seems like in the question I linked to the issue is that they do not allocation the char on the heap. I am not sure what's happening here. Using identical calls to strcpy on another struct with a field char name[9] works just fine.
What am I missing? What have I over looked?
Thanks in advance!
You've forgotten to initialize the temp pointer, so it's pointing to random memory. When you then write
strcpy(temp->name, mm);
You're following a pointer to a random address and writing bytes there, hence the segfault.
The problem is in the following line of your code
usage *temp;
strcpy(temp->name,nm); //segfault here.
You are not initializing the temp pointer so it is taking a garbage value.
Try initializing it before strcpy
usage *temp = malloc(sizeof(usage));
Hope this helps.
Here's my issue:
in other calls I make sure to set temp = malloc(sizeof(struct)); not in this one so I'm trying to write to memory that hasn't been allocated!.
The problem with your code is clear, and the SegFault happens in the exact location where it should. The reason is that you are using memory you haven't previously allocated.
void addUse(int index,char *nm, int addr){
usage *temp;
strcpy(temp->name,nm); //segfault here.
// ...
}
When you declare "usage *temp;" you're creating a pointer temp of type usage. Terrific. But... where is the pointer pointing to? You don't know. The value of temp, the memory address it contains is the garbage that happens to be in the place it occupies in memory when it is created (other programming languages give a default value to uninitialized variables, but C is not in that group).
So... you're being lucky. Your program is best described as "undefined behaviour", since it is possible that temp contains a memory address that casually is unoccupied: your program could run pass this function, crash elsewhere, and you would not have a clue about why.
Another problem is that you should return the new struct usage, while your function is returning void.
This is the function as it should be:
usage * addUse(int index,char *nm, int addr){
usage *temp = malloc(sizeof(usage));
if ( temp == NULL) {
fprintf(stderr, "Not enough memory");
exit(EXIT_FAILURE);
}
strcpy(temp->name,nm); //segfault here.
temp->loc = addr;
temp->next= NULL;
/* more processing */
return temp;
}
I understand that you should link the pointer returned by addUse() to a linked list.
Hope this helps.
Related
I am studying C (self-study, not in an educational institution) and have been trying to build a hashtable data structure as part of my learning.
Please refer to this hopefully reproducible example:
#include <stdio.h>
#include <stdlib.h>
struct table_item {
char *name;
char gender;
char *birthdate;
char *address;
};
struct list_node {
struct table_item *data;
struct list_node *next;
unsigned long long hash_key;
};
struct hashtable {
int table_size;
int num_entries;
struct list_node **entries;
};
struct hashtable* init_hashtable(int size);
void free_hashtable(struct hashtable *table);
int main(void)
{
struct hashtable *hashtable = NULL;
int size_entry = 0;
printf("Input hashtable array size: ");
while (size_entry < 1) {
scanf(" %d", &size_entry);
}
hashtable = init_hashtable(size_entry);
free_hashtable(hashtable);
return 0;
}
struct hashtable* init_hashtable(int size) {
struct hashtable* new_table;
if ((new_table = malloc(sizeof(struct hashtable))) == NULL) {
perror("Error: failed to allocate memory for hash table\n");
exit(EXIT_FAILURE);
}
new_table->table_size = size;
new_table->num_entries = 0;
if ((new_table->entries = malloc(size*sizeof(struct list_node))) == NULL) {
perror("Error: failed to allocate memory for hash table array\n");
exit(EXIT_FAILURE);
}
return new_table;
}
void free_hashtable(struct hashtable *table) {
for (int i = 0; i < table->table_size; i++) {
if (table->entries[i] != NULL) {
free_list(table->entries[i]);
table->entries[i] = NULL;
}
}
free(table->entries);
free(table);
}
My issue is that trying to free the table always fails, even if I have not added anything to it.
I used GDB to check the issue. It seems that, in the above for loop, if (table->entries[i] != NULL) always fires (such as when i=0) even when I haven't added anything. This results in my free_list function trying to free inappropriate memory, which is why I get the stack dump.
Somehow it seems that table->entries[i] is actually not NULL but rather has a struct list_node * type, causing the if condition to fire inappropriately. Could somebody please explain to me why this is?
I was hoping that I could use this for loop to go through the entries array and only free memory where malloced nodes exist, but as it stands this will just crash my program. I am not sure how I can alter this to behave as I'd like it to.
Somehow it seems that table->entries[i] is actually not NULL
Indeed, because you never initialized it to NULL.
init_hashtable allocates space using malloc and points table->entries. Now malloc does not initialize the memory it provides. Its contents are garbage, and in particular, there is no reason why it should consist entirely of NULL pointers as your code expects.
If you want table->entries to be full of NULL pointers then you have to explicitly initialize it, either with a loop, or with memset(entries, 0, size*sizeof(struct list_node *)). Or best of all, by calling calloc instead of malloc, which also avoids bugs in case the multiplication size*sizeof(struct list_node *) overflows.
(Technically memset and calloc initialize memory to all-bits-zero, which in theory does not have to correspond to NULL pointers, but it actually does on all systems you are likely to encounter. But to be pedantic, the loop is the only strictly conforming way to do it.)
but rather has a struct list_node * type,
This has nothing to do with types. Types in C are statically determined from declarations, and there is no way for an object to have an unexpected type at runtime. The type of table->entries[i] is struct list_node * no matter what. The question is about the value of that object; you expect it to be NULL but it's not. "Null pointers" are not a separate type in C; NULL is simply a value that a pointer of any type may have.
As Avi Berger points out, there is another bug in that the size calculation in the malloc should be size*sizeof(struct list_node *) not sizeof(struct list_node). Each element is not a struct list_node but rather a pointer. In this case a struct list_node is larger than a pointer, so it's just wasting memory and not causing any other harm, but it should be fixed.
Somehow it seems that table->entries[i] is actually not NULL but rather has a struct list_node * type, causing the if condition to fire inappropriately. Could somebody please explain to me why this is?
You dynamically allocate space for table->entries. The initial contents of that allocated space are unspecified, so until you assign values to its contents, it is unsafe to have any particular expectations about them. In particular, you cannot assume that any or all elements will contain null pointers.
If you want to rely on those values to tell you something about what kind of cleanup needs to be performed, then you should set them all to appropriate values, I guess NULL, immediately after allocating the space.
Note also that there are null pointer values of every pointer type, so being null and having type struct list_node * are not mutually exclusive.
I am trying to build an initialize a hashtable whose pointers point to another struct in my program. But it seems to give me a segfault when I try to initialize(H). I think I may be allocating memory incorrectly, but I'm not sure if that's what a segmentation fault actually means. The way it is set up, H->hashtable should be an array of hashnodes, right? hashnodes themselves are the pointers to my other structs. Why am I only getting a seg fault at initialize?
#include <stdio.h>
#include <stdlib.h>
typedef struct Position{
char data[12];
struct Hashnode *previous;
struct Position *next;
char letter;
char direction[5];
} *position;
typedef struct Hashnode{
struct Position *INSIDE;
} *hashnode;
typedef struct hash_table{
hashnode *hashtable
} *HTABLE;
HTABLE NewHashtable(){
HTABLE H = (HTABLE) malloc(sizeof(struct hash_table));
if(H == NULL){ printf("Malloc for new hashtable failed."); exit(1);}
return H;
}
void initialize(HTABLE H){
H->hashtable = (hashnode*) malloc(100003*sizeof(hashnode));
int toofer;
for(toofer = 0; toofer<100003; toofer++){
H->hashtable[toofer]->INSIDE = NULL;
}
}
int main(){
HTABLE H = NewHashtable();
initialize(H);
return 0;
}
This:
HTABLE H = (HTABLE) malloc(sizeof(struct hash_table));
is just horrible. It mixes a typedef:ed pointer (why do people still do this?) with the underlying struct name, making it the reader's job to make sure they match. Plus, that cast is a bad idea, too.
It should be:
HTABLE H = malloc(sizeof *H);
if you insist on keeping the typedef.
That said, the code in initialize() is probably failing its malloc() call, which is not checked before being relied on. This is a very bad idea.
Further, there's confusion about what exactly is being allocated. The malloc() code allocates 100003*sizeof(hashnode), but hashnode is (again) typedef:ed as a pointer, not a struct. Then the pointers are dereferenced in the loop, causing mayhem.
H->hashtable = (hashnode*) malloc(100003*sizeof(hashnode));
int toofer;
for(toofer = 0; toofer<100003; toofer++){
H->hashtable[toofer]->INSIDE = NULL;
}
}
The first line allocates a bunch of memory for H->hashtable. It contains random garbage.
Thus, when you enter the loop, H->hashtable[0] is random garbage (because all of H->hashtable is random garbage). But you attempt to follow that random garbage pointer in in your loop. Dereferencing an uninitialized pointer is the fastest way to get a segmentation fault.
Here's a way to help you see it. Say you decided to zero that memory to be safe. Your code would be:
H->hashtable = (hashnode*) malloc(100003*sizeof(hashnode));
memset(H->hashtable, 0, 100003 * sizeof(hashnode));
int toofer;
for(toofer = 0; toofer<100003; toofer++){
H->hashtable[toofer]->INSIDE = NULL;
}
}
Clearly, after that memset, *(H->hashtable) is 0 since that sets all of H->hashtable to 0. So H->hashtable[0] is 0 too and thus H->hashtable[toofer]->INSIDE dereferences a null pointer.
H->hashtable = (hashnode*) malloc(100003*sizeof(hashnode));
should better be
...sizeof(struct Hashnode)...
I have a generic linked-list that holds data of type void* I am trying to populate my list with type struct employee, eventually I would like to destruct the object struct employee as well.
Consider this generic linked-list header file (i have tested it with type char*):
struct accListNode //the nodes of a linked-list for any data type
{
void *data; //generic pointer to any data type
struct accListNode *next; //the next node in the list
};
struct accList //a linked-list consisting of accListNodes
{
struct accListNode *head;
struct accListNode *tail;
int size;
};
void accList_allocate(struct accList *theList); //allocate the accList and set to NULL
void appendToEnd(void *data, struct accList *theList); //append data to the end of the accList
void removeData(void *data, struct accList *theList); //removes data from accList
--------------------------------------------------------------------------------------
Consider the employee structure
struct employee
{
char name[20];
float wageRate;
}
Now consider this sample testcase that will be called from main():
void test2()
{
struct accList secondList;
struct employee *emp = Malloc(sizeof(struct employee));
emp->name = "Dan";
emp->wageRate =.5;
struct employee *emp2 = Malloc(sizeof(struct employee));
emp2->name = "Stan";
emp2->wageRate = .3;
accList_allocate(&secondList);
appendToEnd(emp, &secondList);
appendToEnd(emp2, &secondList);
printf("Employee: %s\n", ((struct employee*)secondList.head->data)->name); //cast to type struct employee
printf("Employee2: %s\n", ((struct employee*)secondList.tail->data)->name);
}
Why does the answer that I posted below solve my problem? I believe it has something to do with pointers and memory allocation. The function Malloc() that i use is a custom malloc that checks for NULL being returned.
Here is a link to my entire generic linked list implementation: https://codereview.stackexchange.com/questions/13007/c-linked-list-implementation
The problem is this accList_allocate() and your use of it.
struct accList secondList;
accList_allocate(&secondList);
In the original test2() secondList is memory on the stack. &secondList is a pointer to that memory. When you call accList_allocate() a copy of the pointer is passed in pointing at the stack memory. Malloc() then returns a chunk of memory and assigns it to the copy of the pointer, not the original secondList.
Coming back out, secondList is still pointing at uninitialised memory on the stack so the call to appendToEnd() fails.
The same happens with the answer except secondList just happens to be free of junk. Possibly by chance, possibly by design of the compiler. Either way it is not something you should rely on.
Either:
struct accList *secondList = NULL;
accList_allocate(&secondList);
And change accList_allocate()
accList_allocate(struct accList **theList) {
*theList = Malloc(sizeof(struct accList));
(*theList)->head = NULL;
(*theList)->tail = NULL;
(*theList)->size = 0;
}
OR
struct accList secondList;
accList_initialise(secondList);
With accList_allocate() changed to accList_initialise() because it does not allocate
accList_initialise(struct accList *theList) {
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
I think that your problem is this:
You've allocated secondList on the stack in your original test2 function.
The stack memory is probably dirty, so secondList requires initialization
Your accList_allocate function takes a pointer to the list, but then overwrites it with the Malloc call. This means that the pointer you passed in is never initialized.
When test2 tries to run, it hits a bad pointer (because the memory isn't initialized).
The reason that it works when you allocate it in main is that your C compiler probably zeros the stack when the program starts. When main allocates a variable on the stack, that allocation is persistent (until the program ends), so secondList is actually, and accidentally, properly initialized when you allocate it in main.
Your current accList_allocate doesn't actually initialize the pointer that's been passed in, and the rest of your code will never see the pointer that it allocates with Malloc. To solve your problem, I would create a new function: accList_initialize whose only job is to initialize the list:
void accList_initialize(struct accList* theList)
{
// NO malloc
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
Use this, instead of accList_allocate in your original test2 function. If you really want to allocate the list on the heap, then you should do so (and not mix it with a struct allocated on the stack). Have accList_allocate return a pointer to the allocated structure:
struct accList* accList_allocate(void)
{
struct accList* theList = Malloc( sizeof(struct accList) );
accList_initialize(theList);
return theList;
}
Two things I see wrong here based on the original code, in the above question,
What you've seen is undefined behaviour and arose from that is the bus error message as you were assigning a string literal to the variable, when in fact you should have been using the strcpy function, you've edited your original code accordinly so.. something to keep in mind in the future :)
The usage of the word Malloc is going to cause confusion, especially in peer-review, the reviewers are going to have a brain fart and say "whoa, what's this, should that not be malloc?" and very likely raise it up. (Basically, do not call custom functions that have similar sounding names as the C standard library functions)
You're not checking for the NULL, what if your souped up version of Malloc failed then emp is going to be NULL! Always check it no matter how trivial or your thinking is "Ah sher the platform has heaps of memory on it, 4GB RAM no problem, will not bother to check for NULL"
Have a look at this question posted elsewhere to explain what is a bus error.
Edit: Using linked list structures, in how the parameters in the function is called is crucial to the understanding of it. Notice the usage of &, meaning take the address of the variable that points to the linked list structure, and passing it by reference, not passing by value which is a copy of the variable. This same rule applies to usage of pointers also in general :)
You've got the parameters slightly out of place in the first code in your question, if you were using double-pointers in the parameter list then yes, using &secondList would have worked.
It may depend on how your Employee structure is designed, but you should note that
strcpy(emp->name, "Dan");
and
emp->name = "Dan";
function differently. In particular, the latter is a likely source of bus errors because you generally cannot write to string literals in this way. Especially if your code has something like
name = "NONE"
or the like.
EDIT: Okay, so with the design of the employee struct, the problem is this:
You can't assign to arrays. The C Standard includes a list of modifiable lvalues and arrays are not one of them.
char name[20];
name = "JAMES" //illegal
strcpy is fine - it just goes to the memory address dereferenced by name[0] and copies "JAMES\0" into the memory there, one byte at a time.
beginner in C here. Is this legal here? I keep getting status access violation when i run this code:
struct point {
char *x;
char *y;
}
int main()
{
....
struct point *pt;
for (;;)
{
....
pt = process_message(message);
printf("%s",pt->x);
...
}
}
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point))
strncpy(pt->x, message, 4);
return pt;
}
EDIT
Hi guys i made some changes...but still getting the access violation. pls advise!
You need to allocate memory for struct point in process_message.
Something like this:
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point));
// ... do some processing ...
return pt;
}
Of course, you should free the pointer at some point afterwards.
Also you should return a struct point in process_message or check your type concordance. If you look carefully, you will see you are returning a struct price* but you are expecting (on the calling side) a struct point *.
UPDATE:
Now that question was updated, you will also need to allocate memory for char *x and char *y if you want to do this:
strncpy(pt->x, message, 4);
I would recommend to read a little bit (or a lot) about memory management and pointers in C++. Pointers are not the only way of dealing with data in C Programming Language.
(NO ERROR CHECKING DONE FOR CODE SIMPLICITY)
Your main function is OK. Your problem is in process_message, where you're using a pointer-to-a-struct but not allocating any memory for it, accessing it, then returning it. Declaring a pointer alone does not create the memory to hold the struct. So you should allocate (use malloc for example) the memory for the struct, so that the memory will "exist" after the end of the function. Then you can return the pointer to it as you're doing, and then you would free it in main when you were done with it.
There are possibly better ways to accomplish the goal here given the simple operation you're doing. One is to keep one "scratch" struct local in your main function, and pass its address to process message:
struct point pt;
process_message(message, &pt);
printf("%s", pt.x);
This will "Reuse" the local memory and not require the alloc/free. Notice here that you don't return anything, you just "fill in" the struct in the process function.
Finally, if you're using a modern version of C, you can actually just return the full structure from the function if you want:
struct point process_message(char* message)
{
struct point pt;
... do some processing ...
return pt;
}
And call it like this:
struct point pt = process_message(message);
Remember to allocate memory in the function process_message
pt = malloc (sizeof (struct point));
/* do processing */
return pt;
also after you have finished working with pt remember to free it free (pt).
EDIT
Also you need to allocate the memory blocks to store the strings to x and y in the function, after allocation of the pt. When you have done working, you need to free the strings first (memory blocks) and then the structure.
Whenever you create pointer, it's just a sizeof(ptr) memory , which points to some data. So you must have some memory where your data is stored.
So either allocate memory in your function ( process_message), or in calling function.
it should go like
struct point *pt = (struct point*)malloc(sizeof(struct point));
As written now, you're allocating the struct point, but that structure contains pointers to strings, and not storage for the strings themselves. You need to allocate space for the strings before you copy into them:
pt = malloc(1*sizeof(struct point));
pt->x = (char *)malloc( strlen(message) + 1);
Don't forget to do the same for pt->y before you use it, and don't forget to separately free the storage allocated for the strings, and then that allocated for the struct.
Am unable to run this code...
#include<cstdio>
int main()
{
struct a{
int b;
struct a *next;
};
typedef struct a no;
no *n;
n->b = 12;
n->next = NULL;
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
return 0;
}
When you say:
no *n;
you get an uninitialised pointer. When you use that pointer, you get undefined behaviour.
You allocated space for a pointer to a structure, but you didn't allocate space for the actual structure. This means that you don't have a memory address for the structure you are using.
In addition, the pointer points to some random memory address because you didn't initialize it. As a result, you could be trying to read and write to memory that doesn't belong to you, which can cause your program or even your system to crash because of the undefined behavior that results.
As #Neil Butterworth said, you get an uninitialised pointer. This mean that this pointer could point to anywhere, thus giving an access violation error. The way to fix this is simple, just call malloc() before using that pointer. malloc() gives that pointer a valid and usable address, so no one will complain about that.
You're declaring a struct INSIDE a function.
Declare the struct OUTSIDE of the function.
The typedef should be declared outside the function too.
#include<cstdio>
struct a{
int b;
struct a *next;
};
typedef struct a no;
int main()
{
///... your code...
}
try something like this:
no *n = (no*)malloc(sizeof(no));
#include <cstdio>
/* declaring the struct in the function definition may be possible (I'm not sure,
actually, haha). Unless you have a GOOD reason, it's good practice to declare
structs, globals, typedefs, etc... outside the function */
typedef struct a{
int b;
struct a *next;
} no;
int main()
{
no *n;
/* Here, you have a pointer. Remember these are simply (generally) 32-bit values
defined in your stack space used to store a memory location which points to your
ACTUAL struct a! Depending on what USED to be in the stack space, this could
point ANYWHERE in memory, but usually you will find that it points to the NULL
memory location, which is just address "0". To get this to point to something,
you have to allocate empty space on your heap to store your struct... */
n = malloc(sizeof(no));
/* Now your pointer n points to an allocated 'struct a', and you can use it like
normal */
n->b = 12;
n->next = NULL;
/* You just set n->next, which is another 'no' pointer, to NULL. This means that
n->next points nowhere. So, just like above you have to malloc another instance
of the struct! */
n->next = malloc(sizeof(no));
/* NOW you can use n->next with no ill effects! */
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
/* After you're done with your structs, you want to free them using the POINTERS
that reference them */
free(n->next);
free(n);
return 0;
}