Sign in to follow this  
nlbs

realloc fails segfault

Recommended Posts

nlbs    100
//Written in C not C++
#include <stdio.h>
#include <stdlib.h>

struct StudentInfo{
	char* name;
	unsigned int roll;
};

typedef struct StudentInfo StdInfo;

int main(int argc, char** argv){
	StdInfo* students;
	unsigned int size = 3, i=0;
	unsigned short int s = 1;

	students = malloc( size*sizeof(StdInfo) );

	do{
		printf("Enter name of Student %d :\t", i);
		scanf("%s", &(students[i].name));
		printf("Enter Roll of Student %d :\t", i);
		scanf("%d", &(students[i].roll));
		printf("\n\nEnter another ? (1/0):\t");
		scanf("%d", &s);
		if(s == 1){
			size *= 2;
			students = realloc( students, size*sizeof(StdInfo) );
		}
		i++;
	}while(s == 1);

	free(students);
	students = 0x0;

	return 0;
}

Why does the above code makes segfault ??

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by nlbs
So how can I solve it ??
Allocate space for the name.

After students = malloc( size*sizeof(StdInfo) );, add:

for(i=0; i<size; ++i)
students [i].name = malloc(256);



That'll let you enter up to 255 character names. If you want to completely prevent buffer overruns, you'll need to use some function other than scanf.

EDIT: And you'll need to reallocate the name buffers accordingly, and free them at shutdown. Yet another reason to prefer C++...

Share this post


Link to post
Share on other sites
nlbs    100
I think realloc is making the crash.
as even if I remove the char* name from the structure it crashes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct StudentInfo{
//char* name;
unsigned int roll;
};

typedef struct StudentInfo StdInfo;

int main(int argc, char** argv){
StdInfo* students;
unsigned int size = 3, i=0, j;
unsigned short int s = 1;
char* dump_name;

students = malloc( size*sizeof(StdInfo) );

do{
//StudentInfo.name removed

printf("Enter Roll of Student %d :\t", i);
scanf("%d", &(students[i].roll));
printf("\n\nEnter another ? (1/0):\t");
scanf("%d", &s);
if(s == 1){
size *= 2;
students = realloc( students, size*sizeof(StdInfo) );
}
i++;
}while(s == 1);

free(students);
students = 0x0;

return 0;
}

This one also crashes.

Share this post


Link to post
Share on other sites
SiCrane    11839
The only other problem I see with that code is that you're using %d to fill a short, which will treat the pointer as a pointer to int, probably causing stack corruption.

Share this post


Link to post
Share on other sites
nlbs    100
I dont think its a problem cause language supports coertion for int to short int.
however can you provide a Solution ??

Share this post


Link to post
Share on other sites
swiftcoder    18437
Quote:
Original post by nlbs
I dont think its a problem cause language supports coertion for int to short int.
This is true for simple assignment, but it isn't true for pointers - especially in the case of printf (or any other variadic function), because it recieves no type information at all, beyond the specifiers in the format string.
Quote:
however can you provide a Solution ??
Check the man page for printf to find the format specifier for short - I don't recall it offhand. A better solution would be to make s an int anyway, or even better a size_t (which is the type expected by malloc/realloc in most implementations) and use the format specifier for size_t (again, check the man page).

Share this post


Link to post
Share on other sites
MaulingMonkey    1730
Quote:
Original post by nlbs
I dont think its a problem cause language supports coertion for int to short int.

The language lets you convert between the two types, but printf uses the ellipsis construct. This means no automatic conversion takes place, and you need to tell printf the exact type you passed.

Otherwise, it's similar to casting from (short*) to (int*) -- both C and C++ force you to make an explicit cast to do so, because it isn't safe.

This is one of the reasons that, when programming in C++, we always recommend alternatives to printf -- type safe alternatives such as boost::format, or anything else using operator chaining, where your reasoning wouldn't fall flat, and any necessary conversions would be made for you.

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by swiftcoder
Check the man page for printf to find the format specifier for short - I don't recall it offhand.

That probably has something to do with the fact that there isn't one. At least not in standard C. Your compiler may support non-standard format specifier extensions.
Quote:
A better solution would be to make s an int anyway, or even better a size_t (which is the type expected by malloc/realloc in most implementations) and use the format specifier for size_t (again, check the man page).

Again, no such thing. For scanf() integer format specifiers you've got pointer to int and pointer to unsigned int.

Share this post


Link to post
Share on other sites
Gage64    1235
Quote:
Original post by SiCrane
Quote:
Original post by swiftcoder
Check the man page for printf to find the format specifier for short - I don't recall it offhand.

That probably has something to do with the fact that there isn't one. At least not in standard C. Your compiler may support non-standard format specifier extensions.


Here it says that you need to add an h to the d. Are you saying that's not standard behavior?

Share this post


Link to post
Share on other sites
swiftcoder    18437
Quote:
Original post by SiCrane
Quote:
Original post by swiftcoder
Check the man page for printf to find the format specifier for short - I don't recall it offhand.

That probably has something to do with the fact that there isn't one. At least not in standard C. Your compiler may support non-standard format specifier extensions.
Quote:
A better solution would be to make s an int anyway, or even better a size_t (which is the type expected by malloc/realloc in most implementations) and use the format specifier for size_t (again, check the man page).

Again, no such thing. For scanf() integer format specifiers you've got pointer to int and pointer to unsigned int.
Fair enough, I tend to take the man page as gospel, and don't have a copy of the standard handy. However, I haven't had a problem *yet* (across Windows/linux/Mac) using "%hd" for signed short, and "%zu" for size_t.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this