realloc causing segmentation fault for unknown reason [duplicate] - c

This question already has answers here:
Why does counting down an unsigned int loop forever in C?
(5 answers)
Proper way to count down with unsigned
(6 answers)
Closed 3 months ago.
I am writing a code, I have a two dimensional char array:
char *encode(char *text, size_t rails) {
char **format = calloc(rails, sizeof(char*));
char *cipherText = calloc(strlen(text), sizeof(char*));
size_t row, column, i;
for (i = column = 0; i < strlen(text); column++) {
for (row = 0; row < rails; row++, i++) {
format[row] = realloc(format[row], sizeof(char) * (column + 1));//works
format[row][column] = text[i];
}
column++;
for (row = rails-1; row >= 0; row--, i++) {
format[row] = realloc(format[row], sizeof(char) * (column + 1));//this causes segmentation fault
format[row][column] = text[i];
}
}
Any why does the realloc causes this in the second time if it's the exact same of the last time

Related

C String Allocation Wonkiness

Having trouble understanding and getting to work String operations in the following code.
Please help, me and my study colleagues are losing our minds over this. ty.
This is a simple method to fill a multi dimensional array with custom strings - which for some reason we cannot figure out for the life of us does simply not work - spits out random junk from the memory instead. Also allocation amounts don't seem to be quite right.
#include <stdio.h>
#include <malloc.h>
#include <string.h>
char*** createKeyPad(int rows, int cols, int num_chars) {
if(num_chars <= 0) return NULL;
char needed = 'a';
char** aptr = NULL;
char*** rptr = NULL;
aptr = (char**) malloc(rows * cols * sizeof(char*));
if(aptr == NULL) {
return NULL;
}
rptr = (char***) malloc(rows * sizeof(char**));
if(rptr == NULL) {
free(aptr);
return NULL;
}
for(int row = 0; row < rows; row++) {
rptr[row] = aptr + (row * cols);
}
for(int row = 0; row < rows; row++) {
for(int col = 0; col < cols; col++) {
char* string;
for(int i = 0; i < num_chars; i++) {
string[i] = needed;
}
string[num_chars] = '\0';
rptr[row][col] = string;
printf("%s", string);
}
}
printf("%s", "hallo");
return rptr;
}
int main() {
printf("Hello, World!\n");
char*** keypad = createKeyPad(5, 5, 3);
for(int row = 0; row < 5; row++) {
for(int col = 0; col < 5; col++) {
printf("%s", keypad[row][col]);
}
printf("\n");
}
}
You have plenty problems in this code.
string is a dangling pointer - ie it was not initialized and does not reference a valid char array
even if string was referencing a valid object you assign the same pointer to all (pseudo)array elements.
Do not use *** pointers.
use the correct type for sizes
Use positive checks and try to minimize function returns.
arrays are indexed from 0 in C and even if the string was referencing an array of num_chars elements, string[num_chars] = '\0'; is accessing an element outside the array bounds.
I would use array pointers and use only one allocation to allocate the space for the whole 3D array.
Use objects instead of types in sizeofs
int createKeyPad(size_t rows, size_t cols, size_t numChars, char (**pad)[cols][numChars])
{
int result = 0;
if(numChars > 1)
{
*pad = malloc(rows * sizeof(**pad));
if(*pad)
{
result = 1;
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
{
for(size_t i = 0; i < numChars - 1; i++)
{
(*pad)[row][col][i] = row * cols + col + '0';
}
(*pad)[row][col][numChars - 1] = 0;
}
}
}
}
return result;
}
int main(void)
{
printf("Hello, World!\n");
char (*keypad)[5][3];
if(createKeyPad(5, 5, 3, &keypad))
{
for(size_t row = 0; row < 5; row++)
{
for(size_t col = 0; col < 5; col++)
{
printf("%s ", keypad[row][col]);
}
printf("\n");
}
}
free(keypad);
}
https://godbolt.org/z/6zY4zbGW3
The main problem is that char* string; followed by string[i] = needed; is dereferencing an invalid pointer because string is not pointing to anything valid.
In the code's current style of allocating one block for each level and dividing the block up, the memory for all the strings could be allocated in one big block:
char* sptr = (char*) malloc(rows * cols * (num_chars + 1) * sizeof(char));
(Note: The (char*) typecast is not required. Also the * sizeof(char) is not required since sizeof(char) is 1 by definition, but I put it in there in case the code is changed to use something other than char at a later date.)
Then the string variable in the nested loop can be initialized as follows:
char* string = sptr + (row * cols + col) * (num_chars + 1);

C how to put content of .txt file into 2D array

Working with C, I am trying to read from a .txt file, line by line, and then put every line into an array. Every line is 200 characters long maximum, and the array can store, lets say 50 lines. If the number of lines exceed 50, I want to dynamically allocate twice as much memory, and so on until it is enough. If I put the if{...} part outside of the while loop, it seems to work, but as soon as I use it inside of the loop it does not. I would appreciate any help.
FILE *fp=fopen(file,"r");
int idx=0;
int row=50;
int col=300;
char temp[row][col];
while (fgets(temp[idx],col,fp)){
if (idx == row) {
char **new = malloc(2 * row * sizeof(char *));
for (int j = 0; j < row; j++) {
new[j] = (char *) malloc(col * sizeof(char) + 1);
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < (col + 1); j++) {
new[i][j] = temp[i][j];
}
}
row = 2 * row;
**temp = **new;
free(new);
}
idx++;
}
fclose(fp);
You cannot change the dimensions of a local array (here temp[row][col]). Instead you need to keep a pointer to such an array. In the following code I use a temp array just to keep one line for fgets, and then copy it immediately into a dynamically allocated storage (arr is the 2d array of lines):
FILE *fp=fopen(file,"r");
int idx=0;
int row=50;
int col=300;
char temp[col];
char **arr = malloc(row*sizeof(char*));
while (fgets(temp,col,fp)){
if (idx == row) {
char **new = realloc(arr, 2 * row * sizeof(char *));
if(!new) abort();
arr = new;
row *= 2;
}
arr[idx++] = strdup(temp);
}
fclose(fp);

dynamically initialize a 3D character array in c [duplicate]

This question already has answers here:
Correctly allocating multi-dimensional arrays
(2 answers)
Closed 4 years ago.
I am trying to initialize a 3D character array, but couldn't. when i execute the program crashes.
I need to store 'T' sets of 'N[i]' no.of words in the ***word.characters in each word are less than 20.
"The program executes when static initialized."
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<math.h>
int main()
{
int i,j,k,T,sum=0;
printf("\nEnter the no of test cases");
scanf("%d",&T);
int *N;
N=(int*)malloc(T*sizeof(int));
int **t;
t=(int**)malloc(T*sizeof(int*));
for(i=0;i<T;i++)
{
t[T]=(int*)malloc(N[i]*sizeof(int));
}
char ***word;
word = (char ***)malloc(T*sizeof(char**));
for (i = 0; i< T; i++)
{
word[T] = (char **) malloc(N[i]*sizeof(char *));
for (j = 0; j < N[i]; j++) {
word[T][N[i]] = (char *)malloc(20*sizeof(char));
}
}
In this line:
t[T]=(int*)malloc(N[i]*sizeof(int));
N[i] is uninitialized.
The same apply 3 times here:
word[T] = (char **) malloc(N[i]*sizeof(char *));
for (j = 0; j < N[i]; j++) {
word[T][N[i]] = (char *)malloc(20*sizeof(char));
}
So after
N=(int*)malloc(T*sizeof(int));
you should add some initialization like:
for(i=0;i<T;i++)
{
N(i) = 10 + i; // or whatever dimension you need
}
BTW: You don't need all the casting of malloc

C: populate multiple dimension array [duplicate]

This question already has answers here:
Correctly allocating multi-dimensional arrays
(2 answers)
Closed 5 years ago.
I have several numbers that i want to insert into Matrix.
This is how i am get all my numbers one by one:
int i, n;
int ch;
int *arr;
int dimension;
int numbers = 0;
char str[512];
// User input.
fgets(str, sizeof str, stdin);
for (i = 0; i <= (strlen(str)); i++)
{
if (str[i] != '\0' && !isspace(str[i]))
{
int num = atoi(&str[i]);
numbers++;
if (i == 0)
{
dimension = num;
arr = allocatearraysize(dimension);
}
// Here i want to add the current number to my `Maxtix`.
}
}
free(arr);
int* allocatearraysize(int size)
{
return (int *)malloc(size * size * sizeof(int));
}
So i try:
arr[0][0] = num;
only for see if thats works but got an error:
expression must have pointer-to-object type
Edit
So if my input is 2 1 2 3 4:
the first number (2) means that my matrix should be 2x2 and i expected 4 numbers after this number (2).
In case the numbers of number not match the first number for example:
3 1 2 3 4
The first number here is 3 so after this number i excepted to 9 numbers so in this case i only want to print error message.
But any way i want to insert this numbers into my Matrix.
You can't access arrays with var[i][j] if it's not a 2-dimensional array.
A possible answer would be :
int i, j, n;
int ch;
int **arr;
int size;
int numbers = 0;
char str[512];
fgets(str, sizeof str, stdin);
size = atoi(&str[0]);
if(size > 1) {
arr = (int**) malloc(size * sizeof(int*))
for (i = 0; i < size; i++)
arr[i] = (int*) malloc(size * sizeof(int));
// Fill with arr[i][j]
free(arr);
}
else {
fprintf(stderr, "Size must be a valid number");
}

how to allocate memory dynamically for a two dimensional array [duplicate]

This question already has answers here:
How do I correctly set up, access, and free a multidimensional array in C?
(5 answers)
Closed 7 years ago.
I had recently been for a interview and they had asked me to write a programe to allocate memory dynamically for a two dimensional array (i=3 and j=2)
int *a = (int*)malloc(i*j*sizeof(int));
You can get a[k][l] with a[k*i+l];
Some of you will hate this, but it is a favorite of mine. The main advantage is that it can be de-allocated through a single free and still allows for access through A[r][c].
#include <stdlib.h>
int main(void)
{
int num_row = 3, num_col = 2, r;
int ** A;
A = malloc(num_row*(sizeof(*A)+num_col*sizeof(**A)));
for (r = 0; r < num_row; r++)
{
A[r] = (int*)(A+num_row)+r*num_col;
}
/* Accessing element at row r and column c is through:
*
* A[r][c].
*/
free(A);
return 0;
}
int i = 3;
int j = 2;
int** a = malloc(i * sizeof(int*));
for (unsigned int k = 0; k < i; k++) {
a[k] = malloc(j * sizeof(int));
}
// Now you can use it.
a[0][0] = 0;
a[2][1] = 3;
Haven't you tried searching the SO question database before asking the question?

Resources