c - Problems with pointers and allocation - c

I have to dynamically allocate a pointer inside a while.
char * allocationg_memory(char [] path p) {
char message[4000];
char c;
unsigned int i = 0;
unsigned int count;
FILE *f;
//open the file
f = fopen(p, "rt");
count = 0;
//copy the contain of the file in message
if (f) {
while ((c = getc(f)) != EOF) {
count++;
message[i] = c;
i++;
}
fclose(f);
}
//allocating the memory
char *str = (char *) malloc(sizeof (char) * (count));
if (str == NULL) {
printf("error allocating memory for string\n");
exit(1);
}
//copy the message
strncpy (str, message, count);
return str;
}
void main {
char * ptr;
do {
//my path dynamically changing
path = path_of_file;
ptr = allocating_memory(path);
printf("%s", ptr);
free(ptr);
} while (1);
}
If I set ptr = NULL it gives me segmentation fault, if I don't, if the next print is bigger than the previus, the 2nd is printed over the 1st. What's wrong with my code?

For starters:
Your initial allocation is for 0 bytes.
You are trying to print what you have allocated as if it were a string.
Your loop never ends.

This works for me. Hopefully it helps
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char * allocating_memory(int c) {
char *str = malloc ( c + 1); // allow an extra for the null
strncpy ( str, "abcdefghijklmnopqustuvwxyx", c);
str[c] = '\0'; // make sure the string is null terminated
return str;
}
int main () {
char * ptr;
int counter = 2;
do {
ptr = NULL;
ptr = allocating_memory(counter);
printf("%s\n", ptr);
free(ptr);
counter++;
} while (counter < 27);
return 0;
}

Related

How do I dynamically create an array of strings using scanf in C

So I have been searching through stack overflow for a little over an hour and I don't understand why this function is giving me a segmentation error. I want to create a string array, scan strings in through scanf, dynamically change the size of each string and return the string array. Can anyone help? Thank you.
char** readScores(int* count) {
int c = 0;
char** arr =(char**)malloc(100 * sizeof(char*));
char* in;
while(scanf("%s", in) != EOF) {
arr[c] = (char*)malloc(strlen(in)+1);
strcpy(arr[c], in);
}
*count = c;
return arr;
}
char* in;
while(scanf("%s", in) != EOF) {
This tells the computer to read from standard input into the char buffer that in points to.
Which does not exist, because in is not initialised to anything (let alone a valid buffer).
I would not use scanf only fgets.
You need to allocate memory dor the arr and for every line referenced by elements of arr
char** readScores(size_t *count) {
size_t lines = 0;
char** arr = NULL, **tmp;
char* in = malloc(MAXLINE), *result;
size_t len;
if(in)
{
do{
result = fgets(in, MAXLINE, stdin);
if(result)
{
len = strlen(in);
tmp = realloc(arr, sizeof(*tmp) * (lines + 1));
if(tmp)
{
arr = tmp;
len = strlen(in);
arr[lines] = malloc(len + (len == 0));
if(arr[lines])
{
if(len) memcpy(arr[lines], in, len - 1);
arr[lines++][len] = 0;
}
else
{
// error handling
}
}
else
{
// error handling
}
}
}while(result);
free(in);
}
*count = lines;
return arr;
}

Problems while dynamically allocating memory for a read input function

I am having trouble with a function that should read a string from the user. I am always getting (null) as the output.
Is this even a "right" approach for that kind of problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getString(char *input);
int main(void)
{
char *arr = NULL;
printf("please enter string: ");
getString(arr);
printf("%s", arr);
return 0;
}
int getString(char *input)
{
int i;
char c;
char *tmp;
input = malloc(sizeof(char));
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
tmp = realloc(input, (i + 2) * sizeof(char));
if (tmp == NULL) {
free(input);
printf("allocation error");
return -1;
}
input = tmp;
input[i] = c;
}
input[i] = '\0';
return 0;
}
If you want to dynamically allocate the string you need to pass a pointer to char*, not just a char *. This way, the function can modify the real char * pointer and the caller will see the result. In your current code, the input variable only exists inside the function and does not affect the variable used by the caller, therefore your arr stays unchanged (NULL).
Something like this:
int getString(char **input)
{
int i;
char c;
char *tmp, *cur = NULL;
// No initial malloc() needed here.
// Let realloc() do the job passing NULL the first time.
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
tmp = realloc(cur, (i + 2) * sizeof(char));
if (tmp == NULL) {
free(cur);
printf("allocation error");
return -1;
}
cur = tmp;
cur[i] = c;
}
cur[i] = '\0';
*input = cur;
return 0;
}
And then pass the parameter like this:
getString(&arr);
You should return the input pointer, since it is local to your function and get deallocated when the program leaves from the function, so in main the arr is still NULL.
int* getString(char *input);
int main(void)
{
//...
arr = getString(arr);
//...
}
int* getString(char *input)
{
//...
return input;
}

Do I need to free a pointer which receives a dynamically allocated object from a function?

I am implementing a function that reads a line in C from stdin. Here is the code:
char * stdin_getline(){
unsigned buffer_size = 100;
char *string = malloc(buffer_size);
char *string_temp;
char temp;
int i=0;
while(1) {
scanf("%c", &temp);
if (temp == '\n') {break;}
if (i == buffer_size-1) {
*(string+buffer_size) = '\0';
string_temp = malloc(buffer_size);
strcpy(string_temp, string);
free(string);
buffer_size *= 2;
string = malloc(buffer_size);
strcpy(string, string_temp);
free(string_temp);
}
*(string+i) = temp;
i++;
}
*(string+i+1) = '\0';
return string;
}
int main() {
char *temp_line;
temp_line = stdin_getline();
printf("%s\n", temp_line);
free(temp_line); // Is this line needed?
return 0;
}
Do I really need to free the temp_line pointer inside the main function?
The function call is irrelevant to the question. Everything that was allocated by malloc must be deallocated using free in order to avoid memory leaks.

Dynamic array of strings

I have to dynamically allocate array of words. Words are stored in a file separated by variable count of white-space characters. I don't know how many words is in the file a they can have variable length.
I have this code:
void readWord(FILE* stream, char *word, char first_c) {
word[0] = first_c;
char val;
int wlen = 1;
// isWhitespac is my function - tests if char is blank or '\n'
while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
wlen++;
word = realloc(word, (wlen+1) * sizeof (char));
word[wlen-1] = val;
}
word[wlen] = '\0';
}
int readList(const char *file) {
FILE* f;
char **arr;
char val;
int wcount = 0;
arr = malloc(sizeof (char*));
f = fopen(file, "r");
while (fscanf(f, " %c", &val) == 1) {
wcount++;
arr = realloc(arr, wcount * sizeof (char *));
arr[wcount - 1] = malloc(sizeof (char));
readWord(f, arr[wcount-1], val);
printf("%s\n", arr[wcount-1]);
}
for (int i = 0; i < wcount; ++i) {
free(arr[i]);
}
free(arr);
fclose(f);
return 0;
}
It appears to work fine, it reads a prints all the words. But when I run the program with Valgrind the are too many errors, which I can't find. Could anyone help me? (I know I have to test if malloc and others went fine, it is just a test func.)
The Valgrind log is quite long, should I post it too?
One of the issues is that you do realloc inside readWord. If realloc allocates a new buffer and doesn't just extend the current one then your code will crash (you will double free the pointer) and this is what Valgrind picks up. To fix this I would rewrite the code so it returns a pointer instead of void.
char * readWord(FILE* stream, char *word, char first_c) {
word[0] = first_c;
char val;
int wlen = 1;
// isWhitespac is my function - tests if char is blank or '\n'
while ((val = fgetc(stream)) != EOF && isWhitespace(val) == 0) {
wlen++;
word = realloc(word, (wlen+1) * sizeof (char));
word[wlen-1] = val;
}
word[wlen] = '\0';
return word;
}
And then change the loop in readList to this:
while (fscanf(f, " %c", &val) == 1) {
wcount++;
arr = realloc(arr, wcount * sizeof (char *));
arr[wcount-1]=malloc(sizeof(char));
arr[wcount - 1] = readWord(f, arr[wcount-1], val);
printf("%s\n", arr[wcount-1]);
}

Why does realloc fail on repeated calls where as allocating a big chunk using malloc works?

I am trying to read in from stdin (passing in value from a file). I am reading each character from the string and storing it into a dynamically allocated string pointer. When needed I realloc the memory. I am trying to get as many characters as possible. Though I can limit it to 100,000 chars. But the realloc fails after some iteration. But if I specify a chunk size big, say 1048567 during the first initialization in malloc, I am able to read the string completely. Why is this?
Below is my program:
#include <stdio.h>
#include <stdlib.h>
int display_mem_alloc_error();
enum {
CHUNK_SIZE = 31 //31 fails. But 1048567 passes.
};
int display_mem_alloc_error() {
fprintf(stderr, "\nError allocating memory");
exit(1);
}
int main(int argc, char **argv) {
int numStr; //number of input strings
int curSize = CHUNK_SIZE; //currently allocated chunk size
int i = 0; //counter
int len = 0; //length of the current string
int c; //will contain a character
char *str = NULL; //will contain the input string
char *str_cp = NULL; //will point to str
char *str_tmp = NULL; //used for realloc
str = malloc(sizeof(*str) * CHUNK_SIZE);
if (str == NULL) {
display_mem_alloc_error();
}
str_cp = str; //store the reference to the allocated memory
scanf("%d\n", &numStr); //get the number of input strings
while (i != numStr) {
if (i >= 1) { //reset
str = str_cp;
len = 0;
curSize = CHUNK_SIZE;
}
c = getchar();
while (c != '\n' && c != '\r') {
*str = (char *) c;
//printf("\nlen: %d -> *str: %c", len, *str);
str = str + 1;
len = len + 1;
*str = '\0';
c = getchar();
if (curSize / len == 1) {
curSize = curSize + CHUNK_SIZE;
//printf("\nlen: %d", len);
printf("\n%d \n", curSize); //NB: If I comment this then the program simply exits. No message is displayed.
str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
if (str_tmp == NULL) {
display_mem_alloc_error();
}
//printf("\nstr_tmp: %d", str_tmp);
//printf("\nstr: %d", str);
//printf("\nstr_cp: %d\n", str_cp);
str_cp = str_tmp;
str_tmp = NULL;
}
}
i = i + 1;
printf("\nlen: %d", len);
//printf("\nEntered string: %s\n", str_cp);
}
str = str_cp;
free(str_cp);
free(str);
str_cp = NULL;
str = NULL;
return 0;
}
Thanks.
When you realloc
str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
if (str_tmp == NULL) {
display_mem_alloc_error();
}
//printf("\nstr_tmp: %d", str_tmp);
//printf("\nstr: %d", str);
//printf("\nstr_cp: %d\n", str_cp);
str_cp = str_tmp;
str_tmp = NULL;
you let str_cp point to the new block of memory, but str still points into the old, now freed block. Thus when you access what str points to in the next iteration, you invoke undefined behaviour.
You need to save the offset of str with respect to str_cp, and after the reallocation, letstr point into the new block at its old offset.
And *str = (char *) c; is wrong, although there is a nonzero chance of it being functionally equivalent to the correct *str = c;.
*str = (char *) c;
This line is wrong.
str is a pointer to char and *str is a char but you are assigning a pointer to char to a char. This cannot be done in C.
Moreover:
scanf("%d\n", &numStr);
The \n in scanf call probably does not what you expect:
http://c-faq.com/stdio/scanfhang.html
And also:
str = str_cp;
free(str_cp);
free(str);
You have a double free here. After the assignment str and str_cp will have the same value so doing:
free(str_cp);
free(str);
is as if you do:
free(str);
free(str);
which is undefined behavior (you cannot free twice).

Resources