I am trying to get an input string by using scanf() in a function, but it keeps failing and I don't know why.
Here is part of my code.
typedef struct node {
int id;
char * name;
char * address;
char * group;
struct node * next;
} data;
void showG(data * head) {
char * n = "";
int i = 0;
data * current = head;
scanf("%s", n);
printf("The group of %s is\n", n);
while (current != NULL) {
if (0 == strcmp(current->group, n)) {
printf("%d,%s,%s\n", current->id, current->name, current->address);
i = 1;
}
current = current->next;
}
if (0 == i) {
printf("no group found");
}
}
In your code,
char * n = "";
makes n point to a string literal which is usually placed in read-only memory area, so cannot be modified. Hence, n cannot be used to scan another input. What you want, is either of below
a char array, like
char n[128] = {0};
a pointer to char with proper memory allocation.
char * n = malloc(128);
Please note, if you use malloc(), after the usage of n is over, you need to free() the memory, too , to avoid memory leak.
Note: after fixing the above issue,change
scanf("%s", n);
to
scanf("%127s", n);
if the allocation is for 128 bytes, to avoid the memory overrun.
Related
I have to dynamically allocate memory using these two functions but I keep getting a segfault. The code takes in strings from a file. I need to dynamically allocate memory for a specific number of monsters using structs, pointers and malloc.
typedef struct monster {
char *name;
char *element;
int population;
} monster;
monster* createMonster(char *name, char *element, int population){
//Copying the data into the monster
monster *temp =(monster*) malloc(sizeof(monster));
strcpy(temp->name, name);
strcpy(temp->element, element);
strcpy(temp->population, population);
return temp;
free(temp);
}
monster** readMonsters(FILE* infile, int *monsterCount){
//getting monster count and creating temp pointers
monster **temp = NULL;
char m_word [8];
fscanf(infile, "%d", monsterCount);
fscanf(infile, "%s", m_word); //reading the word monster to skip it
char* temp_name;
char* temp_element;
int temp_pop;
//allocating memory and creating an array of monster pointers * mcount
temp = (monster**)malloc(*monsterCount * sizeof(monster*));
for(int i = 0; i < monsterCount; i++){
fscanf(infile, "%s",temp_name);
fscanf(infile, "%s",temp_element);
fscanf(infile, "%d",temp_pop);
monster *monster_temp = createMonster(temp_name, temp_element, temp_pop);
temp[i]->name = monster_temp->name;
temp[i]->element = monster_temp->element;
temp[i]->population = monster_temp->population;
}
return temp;
}
You haven't posted the definition of struct monster.
If struct monster contains a lot of char* and you are assigning a char* to it, that char* needs to be allocated somewhere. It doesn't look like temp_name and temp_element have been allocated, which would cause a crash on the scanf.
your code segfault because you write at uninitialized and unallocated pointers
you directly write with strcpy name and element field of your struct but these two field point at unknow location
also, you try strcpy an integer, directly assign it : temp->population = population ;
finally you cannot return temp and free temp, if you return it it will be reused, you must not free it, hopefully the free is never reach as you exit the function one line before :)
for storing your strings into the struct, you have some possibilities
declare them as array of char in your structure : char name[64]
use a buffer in your structure and set the name and element field point on part of it
malloc them with strlen of original strings before the copy
directly point name and element vars of your createMonster function to the pointer, it will use original memory, but it's not suitable here as they come from temporary memory
an example of create monster function using a static common buffer for your strings (untested) :
#define MONSTER_MAX_BF 64
typedef struct monster {
char *name;
char *element;
int population;
char bf[MONSTER_MAX_BF];
} monster;
monster* createMonster(char *name, char *element, int population){
monster *temp =(monster*) malloc(sizeof(monster));
char * lastBf = temp->bf + (MONSTER_MAX_BF - 1); // buffer last char
char *bfp = bf, *p ;
// copy name
temp->name = bfp ;
p = name ;
while( *p && *bfp != lastBf ) *bfp++ = *p++ ;
*bfp++ = 0;
// copy element
temp->element = bfp ;
p = element ;
while( *p && *bfp != lastBf ) *bfp++ = *p++ ;
*bfp = 0;
temp->population = population ;
return temp;
}
hello friends :) i'm practicing C programming. in this program i have a task to make array of string. i have no idea what's wrong here...probably something about realloc, error i get is _crtisvalidheappointer
#define _CRT_SECURE_NO_WARNINGS
#define MAX 100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readString(char **s)
{
int i = 0;
char c;
printf("\nInput string: ");
while ((c = getchar()) != '\n')
{
i++;
*s = realloc(*s, i*sizeof(char*));
if (*s == NULL) { printf("Memory allocation failed!"); exit(1); }
(*s)[i - 1] = c;
}
*s = realloc(*s, (i + 1)*sizeof(char));
if (*s == NULL) { printf("Memory allocation failed!"); exit(1); }
(*s)[i] = '\0';
}
char **load_words()
{
int cnt=0,wordcnt=0,i=0;
char **words = NULL, *input = NULL;
readString(&input);
while (input[cnt] != '\0' && cnt < strlen(input))
{
words = realloc(words, ++wordcnt);//errors in second repeat of the loop
words[wordcnt] = malloc(MAX);
i = 0;
while (input[cnt] != ' ')
{
words[wordcnt][i++] = input[cnt++];
}
words[wordcnt][i] = '\0';
realloc(words[wordcnt], (i + 1)*sizeof(char));
}
realloc(words, wordcnt);
free(input);
return words;
}
void main()
{
int i;
char **words = NULL;
words = load_words();
scanf("%d", &i);
}
can someone help me and tell me what did i do wrong here? this function should return array of strings but array should be double pointer(string matrix)
You need to change
words = realloc(words, ++wordcnt);
to
words = realloc(words, ++wordcnt * sizeof(*words));
Otherwise you are not allocating enough memory.
words[wordcnt] = malloc(MAX);
This also is not correct, you should access words[wordcnt-1].
You are using realloc but you're not saving its return value anywhere. This means the pointers you have still point to the memory that was freed and the newly allocated memory is leaked.
Look at the working function and you'll see how to use it properly.
One thing to realize when reallocating a double-pointer is that the size of type to realloc is always the sizeof (a pointer). It will be the same on any given system no matter the data type at issue. You can generically reallocate a double-pointer as follows:
/** realloc array of pointers ('memptr') to twice current
* number of pointer ('*nptrs'). Note: 'nptrs' is a pointer
* to the current number so that its updated value is preserved.
* no pointer size is required as it is known (simply the size
* of a pointer)
*/
void *xrealloc_dp (void *ptr, size_t *n)
{
void **p = ptr;
void *tmp = realloc (p, 2 * *n * sizeof tmp);
if (!tmp) {
fprintf (stderr, "xrealloc_dp() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE); /* or break; to use existing data */
}
p = tmp;
memset (p + *n, 0, *n * sizeof tmp); /* set new pointers NULL */
*n *= 2;
return p;
}
note: the memset call is optional, but useful if you have initialized all non-assigned pointers to NULL (such as when using NULL as a sentinel)
note2: you are free to pass a parameter setting the exact number of pointers to increase (elements to add) or change the multiplier for the current allocation as needed for your code.
I'm trying to pass in some parameters into one function, store those values into a set of elements in a struct. Then print those values from within the struct, by calling a another function.
Here's what I'm trying to do:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct temp
{
int num;
char * name;
struct temp * nextPtr;
}temp;
temp * test();
char * printTest(temp * print);
int main (void)
{
test("TV",200);
struct temp * t;
printTest(t);
return 0;
}
temp * test(char * name, int num)
{
struct temp * mem = malloc(sizeof(struct temp));
mem->name = malloc(sizeof(strlen(name) + 1));
mem->name = name;
mem->num = num;
mem->nextPtr = NULL;
return mem;
}
char * printTest(temp * print)
{
char * output;
output = malloc(sizeof(struct temp));
print = malloc(sizeof(struct temp));
sprintf(output,"It's name is %s, and it costs %d",print->name,print->num);
return output; //should print "TV" and costs "200"
}
The function printTest, doesn't seem to print out anything, rather if I hardcore printf within it, it prints null values and zero. However, I tried to print the struct values in the test function, which does work after initializing the values.
For example, if I do printf("%d",mem->num); this does print out a value of 200(In the test function).
But the sprintf and return combination in the last function doesn't result in the same result. Any help would be much appreciated!
You're not capturing the value you return from test, therefore it just gets lost:
int main (void)
{
//changed to capture return value of test.
struct temp * t = test("TV",200);
printTest(t);
return 0;
}
Also your print function is wrong:
// this now points to the struct you allocated in test.
char * printTest(temp * print)
{
char * output;
// you don't really want the size of temp here, you want the size
// of your formatted string with enough room for all members of the
// struct pointed to by temp.
output = malloc(sizeof(struct temp));
// you're not using this.
print = malloc(sizeof(struct temp));
// you sprintf from a buffer pointing to nothing, into your output buffer
// writing past the memory you actually allocated.
sprintf(output,"It's name is %s, and it costs %d",print->name,print->num);
// return doesn't print anything, it simply returns the value that your
// function signature specifies, in this case char *
return output; //should print "TV" and costs "200"
}
Try this, you'll take the pointer you allocated, and use printf to write a formatted string to stdout:
// we're not returning anything
void printTest(temp * print ){
if (temp == NULL ){
// nothing to print, just leave.
return;
}
printf("It's name is %s, and it costs %d",print->name,print->num);
return;
}
Also some notes about your test function:
// char is a pointer to a string, from your invocation in main, this is
// a string stored in static read only memory
temp * test(char * name, int num)
{
// you malloc memory for your struct, all good.
struct temp * mem = malloc(sizeof(struct temp));
// you malloc space for the length of the string you want to store.
mem->name = malloc(sizeof(strlen(name) + 1));
// here's a bit of an issue, mem->name is a pointer, and name is a pointer.
// what you're doing here is assigning the pointer name to the variable
// mem->name, but you're NOT actually copying the string - since you
// invoke this method with a static string, nothing will happen and
// to the string passed in, and you'll be able to reference it - but
// you just leaked memory that you allocated for mem->name above.
mem->name = name;
// num is not apointer, it's just a value, therefore it's okay to assign
// like this.
mem->num = num;
mem->nextPtr = NULL;
return mem;
}
Try this instead:
temp * test(char * name, int num)
{
struct temp * mem = malloc(sizeof(struct temp));
// we still malloc room for name, storing the pointer returned by malloc
// in mem->name
mem->name = malloc(sizeof(strlen(name) + 1));
// Now, however, we're going to *copy* the string stored in the memory location
// pointed to by char * name, into the memory location we just allocated,
// pointed to by mem->name
strcpy(mem->name, name);
mem->num = num;
mem->nextPtr = NULL;
return mem;
}
There were many more problems than at first blush. Here is a cleaned up version. You cannot assign a string (e.g. mem->name = name;). You can either allocate for mem->name and then strncpy name to it, or use strdup to allocate and copy at once. In printTest, you must allocate space for output sufficient to hold both the static part of the format string plus print->name and print->num. Look over the following and let me know if you have question.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct temp
{
int num;
char * name;
struct temp * nextPtr;
}temp;
temp * test(char * name, int num);
char * printTest(temp * print);
int main (void)
{
struct temp * t = test("TV",200);
// struct temp * t;
printf ("%s\n", printTest(t));
return 0;
}
temp * test(char * name, int num)
{
struct temp * mem = malloc(sizeof(struct temp));
// mem->name = malloc(sizeof(strlen(name) + 1));
// mem->name = name;
mem->name = strdup (name);
mem->num = num;
mem->nextPtr = NULL;
return mem;
}
char * printTest(temp * print)
{
char *output = NULL;
// output = malloc(sizeof(struct temp));
// print = malloc(sizeof(struct temp));
output = malloc (strlen (print->name) + sizeof print->num + 30);
sprintf(output,"It's name is %s, and it costs %d",print->name,print->num);
return output; //should print "TV" and costs "200"
}
Output
$ ./bin/struct_rtn
It's name is TV, and it costs 200
Additionally, sprintf outputs to a string. It does not output to standard out, i.e. print to the screen, unlike printf which does. You probably want to call printf or puts on your output string.
this line: 'sprintf(output,"It's name is %s, and it costs %d",print->name,print->num)' needs some significant modification. 1) the source fields" print->name and print->num are within an allocated segment of memory However, they have never been set to any specific value, so they contain trash. The destination pointer 'output' points to an allocated memory area, however that area is no bigger that the source area, (and generally, it is expected to be formatted as a 'temp' struct, not as one long string. and because it is only the size of a temp struct, there will be no room for all the extra characters in the sprintf format parameter. Result will be undefined behaviour as the output from sprintf will overrun the allocated memory area
I use this code, with this structure, im trying to make function to add item into array of this structure
typedef struct goods{
char *name;
int num;
} goods;
void addWord(char *what, goods *where, int pnr, int *arrsize, int n){
if (pnr >= *arrsize){
where = (goods*)realloc(where,*arrsize*2*sizeof(goods*));
*arrsize*=2;
}
where[pnr].name = (char*)malloc(strlen(what)*sizeof(char));
strcpy(where[pnr].name,what);
where[pnr].num = n;
}
in main function i have this:
int extstore = 1;
goods *store = (goods*)malloc(1*sizeof(goods*));
addWord(line, store, nr, &extstore, n);
Why am I getting an "invalid next size" runtime-error on the line where = (goods*)realloc(where,*arrsize*2*sizeof(goods*)); in addWord()?
EDIT:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct goods{
char *name;
int r;
} goods;
int main()
{
int linelen, i, nr = 0, current_r;
char *line = NULL;
size_t len = 0;
int extstore = 1;
goods *store;
store = malloc(extstore*sizeof(goods*));
while (1){
while ((linelen = getline(&line, &len, stdin)) != -1){
if (line[linelen - 1] == '\n'){
line[linelen - 1] = '\0';
}
linelen = strlen(line);
if (line[0] == '#'){
if (sscanf(line,"#%d",¤t_r) != 1){
printf("bad input.");
return 0;
} else continue;
}
if (nr >= extstore){
store = realloc(store,extstore * sizeof(goods*) * 2);
extstore*=2;
}
store[nr].name = malloc(strlen(line)*sizeof(char));
strcpy(store[nr].name,line);
store[nr].r = current_r;
nr++;
}
if (linelen == -1) break;
}
printf("\n");
for (i = 0;i < nr;i++){
printf("%s, [id:%d]\n", store[i].name, store[i].r);
}
return 0;
}
extstore * sizeof(goods*) * 2
should be extstore * sizeof(goods) * 2 because the space for structures should be allocated - not just for pointers.
There is a fundamental problem in your code. You are passing pointer by value, which means that any change made to a pointer (not the variable pointed to, but the pointer itself) will not be visible from outside the function. You should pass a pointer by pointer instead, and you should check the result returned from realloc. Secondly, don't assign result of realloc back to same pointer - in case of failure you will lost pointer to memory -> thus, memory leak will occur.
To pass pointer by pointer:
void addWord( char *what, goods **where, size, ...) {
if ( *where == NULL) return; // nothing to do
if ( size < 1) return; // it would result in realloc=free call
goods *res = NULL;
res = realloc( *where, size * sizeof( goods));
if ( res != NULL) {
*where = res;
}
else {
// Error (re)allocating memory
// If realloc() fails the original block is left untouched,
// it is not freed or moved, so here *where is unchanged
}
And there is no need in C to cast a result from malloc.
* Error in `path': realloc(): invalid next size: 0x0000000000ec8010 *
This failure must be because "where" is invalid due to a heap corruption earlier in the execution.
C is pass-by-value.
Which means changing an argument in the function does not change the expression it was initialized from.
Thus, the first time realloc moves the memory, the pointer in main will be bad.
To correct that, either use an extra level of indirection, or preferably return the new value as the result.
(Anyway, you should check for allocation failure (malloc and realloc),
and you should not cast from void* to any pointer-type in C.)
I am new to c programming and I am stuck with this one its a typedef struct and what I would like to do is that I want to create an array from the double pointer from this structure
typedef struct
{
char* firstname;
float price;
}Name,*pName,**ppName;
typedef struct
{
ppName Names;
unsigned int numPerson;
}Book;
And my main which always give me segmentation fault dont mind the loop it is looping until the use says to quit.
int main(void)
{
Book D;
setUpCollection(&D);
while(..)
{
scanf(...);
switch(...)
{
case 1:
if(!AddNewPerson(&D))
return 1;
break;
case 2:
....
case 3:
....
default:
printf("Please enter a valid choice");
}
}
return 0;
}
void setUpCollection(Book* data){
Name name;
pName pname;
pname= malloc(MAX_PERSON* sizeof(pName));
pname= &name;
data->Names= &pname;
data->numPerson= 0;
}
BOOL AddNewPerson(Book* data){
char *title = malloc(sizeof(char));
int len;
Name name;
pName pname;
scanf(...);
len = strlen(firstname);
name.firstname = malloc(len * sizeof(char*));
name.firstname = firstname;
pname= malloc(1);
pname= &name;
data->DVDs[data->numPerson++] = pname;
printf("%0.2f", data->Names[(data->numPerson)-1]->price);
return TRUE;
}
My main problem is that I cant print all the added names and also getting segmentation fault.
There are quite a few errors in your program but let me mention a few:
Doesn't this seem odd to you:
pname= malloc(MAX_PERSON* sizeof(pName));
pname= &name;
you are creating a memory leak by first letting pname point to the array of pName then assigning to &name.
What is this:
char *title = malloc(sizeof(char)); // ?
here you allocate too less space
name.firstname = malloc(len * sizeof(char*));
it should be
name.firstname = malloc(len * sizeof(char) + 1);
or more readable:
name.firstname = malloc(len+1);
this makes no sense again:
pname= malloc(1);
pname= &name;
again you created a memory leak by first letting pname point to a heap block of 1 byte then assigning it to a local variable which you include in data - the local variable is freed up once you leave AddNewPerson() so data will point to garbage.
Instead do something like this (I am no fan of having
typedefs for pointers), also try avoiding naming types
the same way you name variables for clarity:
typedef struct
{
char *firstname;
float price;
} Name;
typedef struct
{
Name** names;
unsigned int numPerson;
} Book;
Now allocate the initial size of your array, the whole point
of having it on the heap is that the array can grow if more
records are added than MAX_PERSONS so you need to keep track
of the number of used records in the array as well as the number
of records allocated
int allocated = MAX_PERSONS;
Book D;
D.names = malloc( allocated * sizeof(Name*) );
D.numPerson = 0;
then loop over user input and add records keeping
track of how many records have been read. Since names
is an array of pointers, you need to allocate a Name
struct each time you add an entry
e.g.
D.names[i] = malloc( sizeof(Name) );
D.names[i]->firstname = strdup(userInputName);
D.names[i]->price = userInputPrice;
then at each iteration check if there is allocated memory left
++i;
if ( i == allocated )
{
// if yes you need to get more memory, use realloc for that
// get e.g. 10 more records
Name* tmp = realloc( D.names, (allocated + 10)*sizeof(Name) );
if ( tmp != NULL )
{
D.names = tmp;
allocated += 10;
}
else
{ .. some error msg .. }
}