#include <stdio.h>
#include <stdlib.h>
void input_all(char* array)
{
int c = 0;
int increse = 20;
int number_of_char = 0;
for (int increment = 0; (c = getchar()) != '\n'; increment++)
{
++number_of_char;
if (number_of_char % 10)
{
array = (char*)realloc(array, increse + sizeof(char));
if (array == NULL)
{
printf("not alocated!");
exit(22);
}
increse += 10;
}
array[increment] = c;
}
printf("%s\n", array);
}
int main(void)
{
char* array = (char*)malloc(10);
if (array == NULL)
{
printf("not alocated\n");
exit(33);
}
input_all(array);
printf("%s\n", array);
return 0;
}
So what I'am trying to do is to fill up "array" with getchar. When I try to print it out I get some garbage values at the end (most of the time). I think the problem is that I'am giving out to much space to "array" with realloc but I have no idea how to fix it. I also tried placing all the sizes to 1 in malloc and realloc and increse so that whenever i get a charcter the size of "array" increses but it still did not work.
Anyone have any idea how ot fix it?
Thanks in advance!
array must be null terminated, otherwise printf and other c-string functions don't know where the end of the string is at.
realloc may not return the same address (although that's not an issue on your PC), you have to use the address of pointer.
You can allocate the whole array realloc. If subsequent realloc fails then you don't necessarily have to exit, you can print error and return the string which was already allocated.
void input_all(char** parray)
{
char* arr = NULL;
int size = 0, i = 0;
while(1)
{
int c = fgetc(stdin);
if (c == '\n' || c == EOF)
break;
if (i == size)
{
size += 10;
char* temp = realloc(arr, size + 1);
if (temp == NULL) { printf("realloc failed\n"); break; }
arr = temp;
}
arr[i++] = (char)c;
}
if(arr)
arr[i] = '\0'; //<- don't forget to terminate the string with 0
*parray = arr;
}
int main(void)
{
char* array = NULL;
input_all(&array);
if (!array)
return 1;
printf("%s\n", array);
free(array);
return 0;
}
Related
This question already has answers here:
C Programming: malloc() inside another function
(9 answers)
Closed 2 years ago.
this function get an memory allocated input(with size : 1 bytes) from user and put it in heap data. it works correctly in function but when this function ends and come back to main, input will be corrupted. it happens when re-allocate function change the address of strings in heap memory. can anyone help me to fix it?
int main() {
char* input = (char*)malloc(sizeof(char));
example(input);
printf("%s", input);
}
void example(char* input) {
int i = 0;
char* a = "qweqeqweqweqweqweqwasdfsdfsdgasdgg";
for (int i = 0; i < 20; i++) {
input = (char*)realloc(input, sizeof(char) * i + 1);
input[i] = a[i];
}
}
The realloc function can return a pointer that was different from what was passed in. If that happens, the copy of input you have in the main function is invalid.
You can fix this by having example return the modified pointer and assigning to back to input in the main function. Also:
Don't cast the return value of realloc
If realloc fails the original pointer is still valid, so assign to a temporary and check the return value
You need to add a terminating null byte to the string and allocate additional space for it.
So your function would become this:
char *example(char* input) {
int i = 0;
char* a = "qweqeqweqweqweqweqwasdfsdfsdgasdgg";
for (int i = 0; i < 20; i++) {
char *tmp = realloc(input, i + 1 + 1);
if (!tmp) {
perror("relloc failed");
free(input);
exit(1);
}
input = tmp;
input[i] = a[i];
}
intput[i] = 0;
return input;
}
And you call it like this:
input = example(input);
You should also move the definition of example to before main, that way it can be called correctly.
The way you call realloc is wrong. You should use a temporary variable to save the pointer because if realloc fails you will loose the reference the original memory block.
char *example(char* input);
int main(void)
{
char *input = malloc(sizeof(*input));
char *tmp;
if((tmp == example(input))) input = tmp;
printf("%s", input);
}
char *example(char* input) {
int i = 0;
char* a = "qweqeqweqweqweqweqwasdfsdfsdgasdgg";
for (int i = 0; i < 20; i++)
{
char *tmp = realloc(input, sizeof(*input) * (i + 2));
if(tmp)
{
input = tmp;
input[i] = a[i];
input[i + 1] = 0;
}
else
{
/* handle allocation error */
}
}
return tmp;
}
You can also use pointer to pointer but you need to save the original pointer to avoid potential memory leak:
int main(void)
{
char *input = malloc(sizeof(*input));
char *tmp = input;
example(&tmp);
if(tmp) input = tmp;
printf("%s", input);
}
void example(char** input) {
int i = 0;
char* a = "qweqeqweqweqweqweqwasdfsdfsdgasdgg";
for (int i = 0; i < 20; i++)
{
*input = realloc(*input, sizeof(*input) * (i + 2));
if(*input)
{
*input = tmp;
(*input)[i] = a[i];
(*input)[i + 1] = 0;
}
else
{
/* handle allocation error */
}
}
}
Another problem in your code: you do not null terminate your string.
You need to read warnings. You have more issues in your code - for example, you call function without prototype.
I'm trying to build in C an array of structures without defining the length of the maximum size of the array.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct text {
char *final;
} text;
int main() {
int n, sizearray = 10, i;
char *str;
text *testo;
testo = (text *)malloc(sizeof(text) * sizearray);
fgets(str, 1024, stdin);
i = 0;
while (str[0] != 'q') {
if (i == sizearray - 1) {
testo = (text *)realloc(testo, sizearray * 2 * sizeof(text));
}
n = strlen(str);
n = n + 1;
testo[i].finale = (char *)malloc(sizeof(char) * n);
strcpy(testo[i].finale, str);
i++;
fgets(str, 1024, stdin);
}
for (i = 0; i < sizearray; i++)
printf("%s \n", testo[i].finale);
return 0;
}
this gives me
process finished with exit code 139 (interrupted by signal 11:SIGSEV).
What am I doing wrong?
There are multiple issues in your code:
[major] str is an uninitialized pointer. You should make it an array of char defined with char str[1024].
[major] you do not adjust sizearray when you double the size of the array, hence you will never reallocate the array after the initial attempt at i = 9.
[major] the final loop goes to sizearray but there are potentially many uninitialized entries at the end of the array. You should stop at the last entry stored into the array.
you should also check the return value of fgets() to avoid an infinite loop upon premature end of file.
you should test for potential memory allocation failures to avoid undefined behavior.
Here is a modified version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct text {
char *finale;
} text;
int main() {
char str[1024];
text *testo = NULL;
size_t sizearray = 0;
size_t i, n = 0;
while (fgets(str, sizeof str, stdin) && *str != 'q') {
if (n == sizearray) {
/* increase the size of the array by the golden ratio */
sizearray += sizearray / 2 + sizearray / 8 + 10;
testo = realloc(testo, sizearray * sizeof(text));
if (testo == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
}
testo[n].finale = strdup(str);
if (testo[n].finale == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
n++;
}
for (i = 0; i < n; i++) {
printf("%s", testo[i].finale);
}
for (i = 0; i < n; i++) {
free(testo[i].finale);
}
free(testo);
return 0;
}
str is uninitialized. Either allocate memory with malloc or define it as an array with char str[1024].
The code below reads characters and splits them into C-style strings when a delimiter is encountered, then it stores the words (white-space-separated sequences of characters) in string array till a sentinel is encountered; updates size of string array:
#include <stdio.h> // printf()
#include <stdlib.h> // malloc(); realloc()
#include <string.h> // strcmp()
#include <stddef.h> // size_t
void print_array(char* arr[ ], size_t size); // forward declaration to use in to_array()
char* get_word(char delimiter)
{
size_t size = 8;
size_t index = 0;
int c = 0;
char* word = 0;
char* expand_word = 0;
word = (char*) malloc(sizeof(char) * size);
if (word == NULL)
{
perror("get_word::bad malloc!\n");
exit(-1);
}
while ((c = getchar()) != EOF && c != delimiter && c != '\n')
{
if (index >= size)
{
size *= 2;
expand_word = (char*) realloc(word, sizeof(char) * size);
if (expand_word == NULL)
{
perror("get_word::bad realloc!\n");
exit(-1);
}
word = expand_word;
}
word[index++] = c;
}
word[index] = 0;
return word;
}
//-------------------------------------------------------------------------------------
void to_array(char* arr[ ], size_t* size, char* sentinel)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char delimiter = ' ';
while ((word = get_word(delimiter)) && strcmp(word, sentinel) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc(arr, sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
arr = expand_arr;
}
arr[index++] = word;
}
(*size) = index;
// print_array(arr, *size); // <---- here, all words printed OK.
// getchar();
}
//-------------------------------------------------------------------------------------
void print_array(char* arr[ ], size_t size)
{
size_t i = 0;
printf("{ ");
for (i; i < size; ++i)
{
printf("%s", arr[i]);
if (i < size - 1)
{
printf(", ");
}
}
printf(" }\n");
}
//-------------------------------------------------------------------------------------
int main()
{
size_t size = 4;
char** arr = 0;
char* sentinel = "quit";
arr = (char**) malloc(sizeof(char*) * size);
if (arr == NULL)
{
perror("array of strings::bad malloc!\n");
exit(-1);
}
printf("Type a sentence and get each word as an array element:\n");
to_array(arr, &size, sentinel);
printf("Words:\n");
print_array(arr, size); // <--------- here, error!
getchar();
}
When trying to print the string array, I get:
Access violation reading location 0xcd007361.
Why I can't print the strings in arr at the end?
P.S.: I guess that the problem comes from the pointer arithmetic and the reallocation of the char** arr within function to_array(). (If previous right) I'm not sure what would be the standard way to deal with it?
Problem: the first parameter in void to_array(), i.e. char* arr[ ] passes a copy of a pointer to array of char. Every change on the pointer made inside the function does not affect the actual pointer to char array outside, specifically the function realloc() may move the initial memory block to a new location, which would invalidate the pointer passed as first parameter.
Solution: either to modify the function void to_array() to return the modified arr, or to modify the first parameter of the function to char** arr[ ]. The latter was chosen and the modified code looks like this:
void to_array(char** arr[ ], size_t* size, char* quit)
{
size_t index = 0;
char* word = 0;
char** expand_arr = 0;
char sentinel = ' ';
while ((word = get_word(sentinel)) && strcmp(word, quit) != 0)
{
if (index >= (*size))
{
(*size) *= 2;
expand_arr = (char**) realloc((*arr), sizeof(char*) * (*size));
if (expand_arr == NULL)
{
perror("to_array::bad realloc!\n");
exit(-1);
}
(*arr) = expand_arr;
}
(*arr)[index++] = word;
}
(*size) = index;
}
then the function call must be done as:
to_array(&arr, &size, quit);
I'm writing code for an assignment where we have to create a hashtable. One of the functions is to get all the keys within the hash table and assign it into a char* ** (triple pointer) given by the parameters. The char* ** is presumed to be empty, and so we have to allocate memory to it within the function to fit all the keys.
The problem I'm having is where, after I allocate memory (and presumably the right amount, with strlen + 1), the program crashes and valgrind gives me an error message of invalid read of size 8, as well as a bunch of unconditional jumps and finally Process terminating with default action of signal 11 (SIGSEGV) Access not within mapped region at address 0x0.
int GetKeys( HashTablePTR hashTablePtr, char ***keysArrayHandle, unsigned int *keyCount )
{
HashTablePTR head;
int counter = 0;
size_t length = 0;
*keyCount = 0;
head = hashTablePtr;
if (NULL == hashTablePtr || 0xDEADBEEF != hashTablePtr[0].sentinel)
{
return(-1);
}
else
{
// Get key count
for (int i = 0; i < (int) head[0].range; i++)
{
hashTablePtr = &(head[i]);
while (NULL != hashTablePtr && NULL != hashTablePtr->key)
{
*keyCount = *keyCount + 1;
hashTablePtr = hashTablePtr->next;
}
}
printf("keyCount: [%d]\n", *keyCount);
}
keysArrayHandle = malloc(sizeof(char **) * (*keyCount));
for(int j = 0; j < (int) head[0].range; j++)
{
hashTablePtr = &(head[j]);
while (NULL != hashTablePtr && NULL != hashTablePtr->key && counter < *keyCount)
{
length = strlen(hashTablePtr->key) + 1;
keysArrayHandle[counter] = malloc(sizeof(char) * length);
printf("%s\n", hashTablePtr->key);
///////SOMETHING IS WRONG WITH THIS LINE UNDERNEATH////////
memcpy(*(keysArrayHandle[counter]), hashTablePtr->key, length);
printf("String copied\n");
counter++;
hashTablePtr = hashTablePtr->next;
}
}
return(0);
}
keysArrayHandle[counter] = malloc(sizeof(char) * length);
returns a pointer to keysArrayHandle[counter].
Then you are using *(keysArrayHandle[counter]) instead of keysArrayHandle[counter] in memcpy.
maybe you should
*(keysArrayHandle[counter]) = malloc(sizeof(char) * length);
valter
I think you should not dereference that pointer there
something = malloc(size);
memcpy(something, x, size); /* instead of memcpy(*something ... */
Also, check mpthe value returned by malloc
I have a function that goes through my array of strings to find out how many times that string occurs with in an array. If found, the string will be set to NULL and a counter keeps track of how many times the string is found. I then call another function within the loop to allocate memory for my frequency array so that I can store count. It seems to work fine, but when I go and create any other variable within main my program crashes. Here are my two functions:
int search(char **table, int **frequency, int wordSize)
{
// Local Declaration
int i, j, k;
int count = 1;
int strCount = 0;
char target[25];
// Statement
for(i = 0, k = 0; i < wordSize; i++)
{
if(table[i] != NULL)
{
strcpy(target, table[i]);
for(j = i + 1; j < wordSize; j++)
{
if(table[j] != NULL &&
strcmp(target, table[j]) == 0 &&
target != table[i])
{
count++;
free(table[j]);
table[j] = NULL;
}
}
strCount += makeFreq(frequency, k, count);
k++;
}
count = 1;
}
return strCount;
}// search
int makeFreq(int **frequency, int k, int count)
{
// Local Declaration
int strCount = 0;
// Statement
frequency[k]=(int*)malloc(sizeof(int));
frequency[k][0] = count;
strCount += 1;
return strCount;
}// makeFreq
Can someone explain to my why my program is crashing?
Here I allocated 1000 pointers for my table.
char** getPoint(void)
{
// Local Declaration
char **table;
// Statement
table = (char**)calloc(MAX_SIZE + 1, sizeof(char));
if(table == NULL)
{
MEM_ERROR, exit(100);
}
return table;
}// getPoint
Than I read I allocate memory for the strings in my file and store it into the array of strings.
int scanFile(char **table, FILE *fpFile)
{
// Local Declaration
int count = 0;
char temp[500];
char **ptr = table;
// Statement
// scan file, allocate, and copy string to array.
while(fscanf(fpFile, "%s", temp) != EOF)
{
*(ptr + count) =(char*)calloc(strlen(temp)+1, sizeof(char));
strcpy(*(ptr + count), temp);
count++;
}
return count;
}// scanFile
Here is how I allocated the array of pointers for my frequency array.
void aloFreqAry(int **frequency, int wordSize)
{
// Local Declaration
// Statement
frequency =(int**)calloc(wordSize + 1, sizeof(int));
if(frequency == NULL)
{
MEM_ERROR, exit(103);
}
return;
}// aloFreqAry
Apart from the problem of the sizes in the allocations (should be sizeof(char*) in the allocation of table, and sizeof(int*) in the allocation of frequency),
void aloFreqAry(int **frequency, int wordSize)
{
// Local Declaration
// Statement
frequency =(int**)calloc(wordSize + 1, sizeof(int));
if(frequency == NULL)
{
MEM_ERROR, exit(103);
}
return;
}// aloFreqAry
doesn't allocate anything to the frequency in the caller. It just allocates memory to the local copy of that pointer, and loses the handle to that when the function returns.
Instead of taking an int** as argument, the function should return one,
frequency = calloc(wordSize + 1, sizeof(int*)); // size of a _pointer_ to int
if(frequency == NULL)
{
MEM_ERROR, exit(103);
}
return frequency;
that you assign in the caller.
This statement looks suspect (where you say "Here I allocated 1000 pointers for my table"):
table = (char**)calloc(MAX_SIZE + 1, sizeof(char));
That doesn't look like an allocation of pointers, but an allocation of a char buffer.
Perhaps you mean:
table = (char**)calloc(MAX_SIZE + 1, sizeof(char*));