I am new to C, and I am trying to solve a coding excercise to practice.
In this particular method, I recevive as parameter a char** swhich always contains 5 strings which I have to process and convert into just one, that is the return value of the method.
Given that there is no way to know how long the final string will be, my idea was to use realloc once I knew the length of each particular string in the array. However, even though it works for a couple of times, after some iterations (In a test case I run, for example it works until size = 43), it suddenly fails with realloc(): invalid next size.
I've searched all around and could not figure out what is that I am doing wrong. Could you please help me figure it out?
char* process(char** s) {
size_t size = 0, last = 0;
char *result, *word, c;
char *temp = NULL;
result = malloc(1);
for (size_t i = 0; i < 5; i++)
{
word = s[i];
size += strlen(word);
temp = realloc(result, size + 1);
if (!temp){
printf("Failed Reallocating");
free(result);
exit(-1);
}
else result = temp;
for (size_t j = last; j < last + size; j++)
{
c = word[j - last];
result[j] = isalpha(c) ? change_char(c) : c;
}
last += strlen(word);
}
result[size] = '\0';
return result;
}
You are writing past the memory size you (re)allocated.
temp = realloc(result, size + 1); means you allocated size+1 chars.
but in the inner loop for (size_t j = last; j < last + size; j++) the j goes all the way to last+size-1 which is guaranteed to be past size+1 and then you write result[j] = isalpha(c) ? change_char(c) : c; so you write past the memory you allocated, overwriting other data, including the meta-data realloc uses to keep track of what is allocated and what is free. Thus it will fail with an almost random error the next time you attempt to reallocate.
The fix is very simple, however. Iterate just up to the new size you allocated, for (size_t j = last; j < size; j++) and it will all work as expected.
Related
so basically there is a function that allocates a new pointer memory and when i try to delocate the old one the program basically crashes my code
char** AddingToTheBook(char** original, int* size, char *number)
{
char** newArray = (char**)malloc(sizeof(char*)*(*size));
//allocating and copying the values
for (int i = 0; i < *size; i++)
{
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))));
strcpy(*(newArray + i), *(original + i));
}
//allocating a new memory to the new number
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
strcpy(*(newArray + (*size)), number);
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
free(original);
return newArray;
}
You are freeing too much of your original memory.
Look at the for loop when you're freeing the memory:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < size; i++)
free(original[i]);
Since size is a int * you will end up with a very big number of iterations which will free to free much more memory than you allocated. To fix this do the following:
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size; i++)
free(original[i]);
Now you're still freeing one element too much since you've incremented *size when adding a new element. The final version to free the original memory is
(*size)++;
//delocating the allocated memories
for (int i = 0; i < *size - 1; i++)
free(original[i]);
strlen only returns the number of chars. Make room for the ending zero
*(newArray + i) = (char*)malloc(sizeof(char)*(strlen(*(original + i))) +1);
Better to strncpy instead of strcpy
How can you go *size ahead in newArray:
*(newArray + (*size)) = (char*)malloc(sizeof(char)*strlen(number));
You can only go *size -1 ahead, since it starts from zero.
In the for loop, it seems you forgot to add the asterisk *
for (int i = 0; i < size; i++)
You can use realloc instead
char** AddingToTheBook(char** original, size_t oldsize, char *number)
{
char** tmp = realloc(**original, (oldsize + 1) * sizeof(char *));
if(tmp)
{
tmp[oldsize] = malloc(strlen(number) + 1'
if(tmp[oldsize])
{
strcpy(tmp[oldsize], number);
}
else
{
/* do something for example realloc back to the old size */
tmp = NULL;
}
}
return tmp;
}
example correct usage
char **tmp = AddingToTheBook(book, size, "Test String")
if(tmp)
{
book = tmp;
size++;
}
else
{
/* do something adding to book failed */
}
I've been trying O(n ^2) sorting algorithm just to practice C, but have encountered this annoying "realloc(): invalid pointer" error and cannot figure out why. I've viewed other explanations but they have not helped too much.
#include <stdio.h>
#include <stdlib.h>
int* removeIndex(int* list, int index, int len){
for(int i = index; i < len - 1; i++){
list[i] = list[i+1];
}
return realloc(list, len - 1);
}
int* sort(int* unsorted, int len){
int* sorted = malloc(len * sizeof(int));
for(int placement = 0; placement < len; placement++){
int smallest_index = 0;
int smallest = unsorted[smallest_index];
int len_unsorted = len - placement;
for(int i = 0; i < len_unsorted; i++){
if (unsorted[i] < smallest){
smallest = unsorted[i];
smallest_index = i;
}
}
unsorted = removeIndex(unsorted, smallest_index, len_unsorted);
sorted[placement] = smallest;
}
return sorted;
}
int main()
{
int len = 5;
int unsorted[5] = {5,4,3,2,1};
int* sorted = sort(unsorted, len);
for(int i = 0; i < len; i++){
printf("%d\n", sorted[i]);
}
return 0;
}
On a side note, why do I get an error if I write
int len = 5;
int unsorted[len] = {5,4,3,2,1};
so I have to force write it as int unsorted[5] = {5,4,3,2,1};
Cheers
The pointer passed to realloc pointing to a array with auto storage duration, which is declared and initialized in main(), and not pointing to a memory block previously allocated with malloc, calloc or realloc.
From realloc [emphasis added]
Reallocates the given area of memory. It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with a call to free or realloc. Otherwise, the results are undefined.
On top of the answer of H.S., I believe the sorting algorithm is ill designed. The first call to the function removeIndex is done with the parameters as so
removeIndex(unsorted, 4, 5)
The for loop is not entered and a reallocation is supposed to take place with realloc(list, 4).
As far as I can see the sorting algorithm cannot work in general. In particular the example you gave with 5,4,3,2,1.
Try to do that with pencil and paper and you will see what I mean.
I know there are many topics of this kind but I've read several of them and still can't figure out what am I doing wrong.
I've successfully generated a char** array. My bubble sort function probably works as well. But when I passed the generated array to the function, only 1 row is copied.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
void sort(char** tab)
{
char* temp;
int i, j, size = sizeof(tab)/sizeof(tab[0]);
printf("%d\n", size);
for(i = 0; i < size; ++i)
{
for(j = i+1; j < size; ++j)
{
if(strcmp(tab[j-1], tab[j]) > 0)
strcpy(temp, tab[j-1]),
strcpy(tab[j-1], tab[j]),
strcpy(tab[j], temp);
}
}
for(i = 0; i < sizeof(tab)/sizeof(tab[0]); ++i)
puts(tab[i]);
}
int main()
{
srand(time(NULL));
int size = rand()%5+5, i, j, s;
char** tab = (char**)malloc(size * sizeof(char*));
for(i = 0; i < size; ++i)
{
s = rand()%9+1;
tab[i] = (char*)malloc(s+1);
for(j = 0; j < s; ++j)
tab[i][j] = 'a'+rand()%26;
tab[i][s] = 0;
}
for(i = 0; i < size; ++i)
puts(tab[i]);
puts("");
sort(tab);
return 0;
}
Here's how the code works.
And when I write size=5 before the loop in the function it returns segmentation fault.
Edit: Same with passing the size of the array as an argument:
http://ideone.com/3Wvncq
Final code
I've fixed all the problems and here's the final code.
I was misinterpreting segmentation fault as the result of assigning a fixed size instead of not allocating the temp variable.
Thank you for all the answers.
Don't calculate size inside function void sort(char** tab) . As in this function it will be calculated as -
int i, j, size = sizeof(tab)/sizeof(tab[0]); // equivalent to sizeof(char **)/sizeof(char*) in function giving wrong length as you desire.
It's length in main(size is generated using rand so no need to find it) and then pass it as argument to function sort.
Declare your function like this -
void sort(char** tab,size_t size)
And while calling from main pass length of tab to it -
sort(tab,size); // size will be number of elements in tab calculated in main
You get segmentation fault because of this -
if(strcmp(tab[j-1], tab[j]) > 0)
strcpy(temp, tab[j-1]),
strcpy(tab[j-1], tab[j]),
strcpy(tab[j], temp);
temp is uninitialized in sort and still you pass it to strcpy thus undefined behaviour . Initialize temp before passing to strcpy.Allocate memory to temp in function sort.
In your sort function you declare the temp variable:
char* temp;
Later you use it as destination (and source) for string copying:
strcpy(temp, tab[j-1]),
But nowhere in between do you make temp point anywhere, temp is uninitialized and that leads to undefined behavior and your crash.
Don't use a pointer, instead declare it as an array of the largest string size possible.
the program is supposed to compare the strings and place them in alphabetical order, but the final printf statement prints garbage...where am i going wrong here?
i have used an array of pointers to strings and declared them in the begining, i have even tried using temp as an array rather than pointer stil doesnt quite work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int j;
int i;
char *temp;
char *string[5] = {"ibrahim","laura","peter","degea"};
for ( i = 0; i< 4;i++)
printf("%s\n", string[i]); //allocating memory
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
for ( i=0; i< 3; i++)
for(j =i+1; j<4; j++)
{
if(strcmp(string[i], string[j]) > 0)
{
strcpy(temp, string[i]);
strcpy(string[i], string[j]);
strcpy(string[j], temp);
}
}
for (i = 0; i< 4; i++)
{
printf("%s\n",string[i]);
puts("\n");
}
free(string);
free(temp);
return 0;
}
string[i] = (char*)malloc (30 * sizeof(char));
This is overwriting the existing initialized values.
EDIT
for( i = 0; i< 10 ;i++)
temp = (char*)malloc(30*sizeof(char));
WHAT? you are allocating memory over and over 10 times on a single pointer?
EDIT 2:
The original post is lost (read Edited). By the time you are reading this answer, both Mr. Jonathan Leffler and this poster migh look like absolute fools in this world.
The code originally destroyed its data array (by allocating new pointers). Now it seems to throw memory away by allocating temp four times (but Jeevan's edit reinstates the old code in indented form). The old code allocated space for strings but never initialized them (having thrown away the value that was in the array beforehand).
NB: any commentary on the code could easily be invalid by the time you're reading the commentary — the code in the question could have changed.
for (i = 0; i < 10; i++)
string[i] = malloc(30);
This code tramples out of the bounds of the string array (dimension is 5). It also loses the data originally in the array.
You need to use strcmp() to compare the strings, but you simply need to swap pointers rather than using strcpy() at all.
The comment // allocating memory beside a printf() statement is misleading, too.
This stands a chance of working. Note that there is no memory allocation:
#include <stdio.h>
#include <string.h>
int main(void)
{
int j;
int i;
char *string[] = { "ibrahim", "laura", "peter", "degea" };
for (i = 0; i < 4; i++)
printf("%s\n", string[i]);
for (i = 0; i < 3; i++)
{
for (j = i+1; j < 4; j++)
{
if (strcmp(string[i], string[j]) > 0)
{
char *temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
for (i = 0; i < 4; i++)
printf("%s\n",string[i]);
return 0;
}
Output:
ibrahim
laura
peter
degea
degea
ibrahim
laura
peter
Comment: don't try sorting thousands of strings using this sort algorithm.
You are overwriting the existing string array contents with malloc, that too 10 times.
Please use braces in your code for better understanding
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
can be written as
for( i = 0; i< 10 ;i++) // why to allocate memory ten times, that too overwriting
{
string[i] = (char*)malloc (30 * sizeof(char));
}
temp = (char*)malloc(30*sizeof(char));
when you declare :
char *string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
the pointer *string[0] to *string[3] allocated to a address in the memory, where will stored the init values "ibrahim","laura"...
when you use malloc function for the pointer string[i] = (char*)malloc (30 * sizeof(char));
the pointer *string[0] to *string[4] will be allocated to another address in the memory. so the value at these address are different from that you initialized (ibrahim,laura).
you should use static array instead dynamic as below
char temp;
char string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
remove all the malloc, free function.
I am struggling with an algorithm to print numbers between 1 and a dynamic variable n into an int.
int n = // dynamic value
int i = 0;
int output[n];
for(i = 0; i < n; i++) {
output[i] = i;
}
However, as n is dynamic, the code won't compile.
Any help would be much appreciated - thanks in advance.
You need to allocate a buffer, or dynamic-sized array, with malloc:
int n = // whatever
int i = 0;
int* output = NULL;
// Allocate the buffer
output = malloc(n * sizeof(int));
if (!output) {
fprintf(stderr, "Failed to allocate.\n");
exit(1);
}
// Do the work with the array
for(i = 0; i < n; i++) {
output[i] = i;
}
// Finished with the array
free(output);
output is a pointer to the beginning of the buffer you allocated, and you can treat it as an array of n ints.
When you're finished with the array, you need to de-allocate the memory with free.
This should work:
int n = // whatever
int i = 0;
int* output = (int*)malloc(sizeof(int)*n);
for(i = 0; i < n; i++) {
output[i] = i;
}
Don't forget to free(output); when you don't need it anymore.
EDIT: Made it C.
If 'n' is changing during runtime, then you could use malloc like suggested in the comments. Then check if you need more space, then automatically realloc more space should it be needed