array of pointers to string , segmentation fault occurs - c

I am learning pointer in c
i have written a small program , but i am getting segmentaion fault
i dont know where i am having the issue
please let me know the issue with the code , it is an array of pointers to string ,
which is in a pointer to structure .
# include <stdio.h>
#include <stdlib.h>
# include <string.h>
char *sum(char **sol) ;
char *summer_sum(char*** solcs) ;
int main()
{
char* datum ="teststring";
sum(&datum);
}
char *sum(char** sol)
{
printf("\n value is : %s",*sol);
summer_sum(&sol);
return "1" ;
}
char *summer_sum(char*** solcs)
{
int i=0;
typedef struct
{
char *asg[40];
}nlist;
nlist *n1;
for( i=0 ; i<= 38 ;i++)
{
n1->asg[i] = calloc(1,1*sizeof(*solcs));
strcpy(n1->asg[i],**solcs);
printf("\n %d value is : %s",i,n1->asg[i]);
}
return NULL;
}

n1 is used uninitialized:
n1->asg[i] = calloc(1,1*sizeof(*solcs));
On the other hand, if you want to allocate enough space for the use of strcpy, you must use strlen instead of sizeof
And you don't need a double or triple pointer, your code simplified:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sum(char *sol);
char *summer_sum(char *solcs);
int main(void)
{
char *datum = "teststring";
sum(datum);
}
void sum(char *sol)
{
printf("\n value is : %s", sol);
summer_sum(sol);
}
char *summer_sum(char *solcs)
{
int i = 0;
size_t len;
typedef struct {
char *asg[40];
} nlist;
nlist *n1 = malloc(sizeof(*n1));
if (n1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
len = strlen(solcs); /* No need to compute len on each iteration */
for (i = 0; i <= 38; i++) { /* you are filling 39 and declared 40 */
n1->asg[i] = calloc(1, len);
/* Always check the result of (m/c/re)alloc */
if (n1->asg[i] == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(n1->asg[i], solcs);
printf("\n %d value is : %s", i, n1->asg[i]);
/* Don't forget to free */
free(n1->asg[i]);
}
free(n1);
return NULL;
}

Before using n1->... You will have allocate memory to n1 as well using calloc()

There are two problems which involves dynamic memory allocation in your code:
n1 is not initialized, you should add a statement like n1 = malloc(sizeof(*n1)); before the for statement in summer_sum()
you did not allocate enough space for each asg[i], you should allocate spaces for these asg[i] by n1->asg[i] = malloc(strlen(**solcs) + 1);

You are using your pointer n1 uninitialized. Your program invokes undefined behavior. In such case you may get either expected or unexpected result.
Second, you are missing a closing brace } in function summer_sum.

Related

Memory allocation for char pointer in a struct

I'm trying to teach C to myself and I'm struggling with what it looks like a very basic thing. I have a struct with a char pointer and I want to dynamically allocate memory and free it once done. What I understand is that I need to allocate memory for both the struct and the char pointer but it looks like I'm missing something because I'm getting a Segmentation fault on the sprintf line.
As an exercise to understand and use malloc and free, I'm trying to build an easy program that takes an int as input and outputs a table with the factorials of all the numbers from 0 to input. Each table entry has its index (int), the result of the factorial (long long int) and the result but in an array of chars format (this is the problematic one).
Here's what I have until now:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str = NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=0; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
I'm probably missing something very obvious and making a silly mistake when allocating the memory for the fact_table[i].str, but I'm struggling to make it work.
In addition to the comments about freeing the memory for n >= 2, if you look at your test after the malloc:
if (fact_table[i].str = NULL) {
You are setting your pointer to NULL. Instead you should write:
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if ( fact_table[i].str == NULL) {
shout("malloc");
}
Just some little recommendation here. This mistake generates a warning on most compiler if you compile using -Wall:
fact.c: In function ‘main’:
fact.c:53:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (fact_table[i].str = NULL) {
^~~~~~~~~~
Also, in order to make sure the compiler will complain if you forget a =, you can compare the values of a variable and of a constant placing the constant on the left: if you write if (NULL = fact_table[i].str), your compiler will complain and notify you with the error.
I reproduced this issue on my setup. We need to fix two issues before program runs ok.
change 'fact_table[i].str = NULL' to 'fact_table[i].str == NULL'. Your previous command directly set 'str' to NULL, which is not expected. This is the reason you met segment error.
In Free memory part, you need to start from index 2. You cannot free memory which doesnot belong to you.
Below code can work well in my setup.
Wish this can help you.
**
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str == NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=2; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
**

Realloc gives invalid pointer error when resizing array

I am trying to make a simple example of a array that increases with its input. The input is a series of numbers and the end of this series is a zero. What I thought of was to increase my array every time a new number is read, but for some reason this does not seem to work since I get an error:
Realloc(): invalid pointer
This is my current code:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize) {
int *newSeries = realloc(series, newSize * sizeof(int));
if (newSeries == NULL) {
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char *argv[]) {
int number;
scanf("%d", &number);
int *numbers;
int size = 0;
while (number != 0) {
numbers = resizeIntArray(numbers, size + 1);
printf("%d ", number);
scanf("%d", &number);
size++;
}
}
You are passing an uninitialised variable to your function, in turn passed to realloc, which needs either a pointer to previously allocated memory, or NULL.
So initialise that variable:
int *numbers = NULL;
There are multiple issues in your code:
you do not initialize numbers to NULL, so realloc() invokes undefined behavior the first time it is called. This is causing the problem you observe.
you do not check the return value of scanf(), causing a potential endless loop and undefined behavior if the input stream does not contain a 0 number.
you do not store the number in the reallocated array...
you do not free the array (minor).
you do not return 0 at the end of main() (minor).
Here a simpler and safer version:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize) {
int *newSeries = realloc(series, newSize * sizeof(int));
if (newSeries == NULL) {
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char *argv[]) {
int number;
int *numbers = NULL;
int i, size = 0;
/* reading the numbers */
while (scanf("%d", &number) == 1 && number != 0) {
numbers = resizeIntArray(numbers, size + 1);
numbers[size++] = number;
}
/* printing the numbers */
for (i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
free(numbers);
return 0;
}
You can try an approach like this. This includes:
Memory checking, with appropriate error messages.
use of malloc() and realloc() to allocate and reallocate memory.
Allocates sufficient space when needed on run-time.
Appropriately checks return value of scanf().
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define EXIT 0
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
int *numbers = NULL;
int number, num_size = 1, count = 0, i;
/* initial allocation of memory */
numbers = malloc(num_size * sizeof(*numbers));
/* small error checking, to be safe */
exit_if_null(numbers, "Initial Allocation");
/* Reading in numbers */
printf("Enter numbers(0 to end): ");
while (scanf("%d", &number) == 1 && number != EXIT) {
/* valid number found, but is there space? */
if (num_size == count) {
num_size *= 2;
/* resize run-time array */
numbers = realloc(numbers, num_size * sizeof(*numbers));
exit_if_null(numbers, "Reallocation");
}
numbers[count++] = number;
}
/* print out numbers */
printf("Your numbers stored in array:\n");
for (i = 0; i < count; i++) {
printf("%d ", numbers[i]);
}
/* free allocated memory, very important */
free(numbers);
return 0;
}
/* helper function for error checking */
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
First you should first allocate some memory before reallocate it. So your code will change as:
#include <stdio.h>
#include <stdlib.h>
int *resizeIntArray(int *series, int newSize){
int *newSeries = realloc(series,newSize*sizeof(int));
if(newSeries == NULL){
printf("Error: Memory allocation failed");
exit(-1);
}
return newSeries;
}
int main(int argc, char* argv[]) {
int number;
scanf("%d",&number);
int *numbers=malloc(sizeof(int));///CHANGED
int size = 1;///CHANGED
while(number != 0){
numbers = resizeIntArray(numbers,size +1);
printf("%d ",number);
scanf("%d",&number);
size++;
}
}
But white you are doing is quite not efficent. A realloc() function hides a free() a malloc() and the worst one: memcpy(). So if you realloc() at each new item, you are going to have a bad time... O(n^2) exactly.
the best way to do it is to allocate a buffer of memory:
struct vector
{
int *numbers;
size_t size;
size_t i;
}
#define DEFAULTBUF 100
int main()
{
struct vector v;
v.numbers=malloc(sizeof(int)*DEFAULTBUF);
v.size=DEFAULTBUF;
v.i=0;
scanf("%d",&number);
while(number != 0 && v.numbers){
if (v.i->=v.size)
{ v.size+=v.size
v.numbers=realloc(v.numbers,sizeof(int)*v.size);
///i leave to you the error handling
}
v.i++;
printf("%d ",number);
scanf("%d",&number);
}
}
The correct use of realloc() malloc() and similar is very important. And also the increasing ratio of the resize. For the datastructure I ever double it. For text I proceed linearly

reallocating struct causes heap corruption

I'm writing a program in C that creates and tries to allocate the struct array. It manages to allocate the first block of memory and i successfully wrote the values on it but when i try to allocate a second time i get a error related to corrupted heap and "Invalid address specified to RtlValidateHeap".
here is my code (sorry for some parts in portuguese):
structs.h:
typedef struct vendedor
{
unsigned int numero;
char * nome;
float salario;
uint8_t comissao;
} VENDEDOR;
functions.h
extern vendedor * vende = (vendedor *)malloc(0);
extern unsigned int vende_sz = 0;
char * receberString()
{
int size = 0;
char temporary;
char * string = NULL;
string = (char *)malloc(size);
while (true)
{
scanf("%c", &temporary);
string = (char *)realloc(string, (size + 1) * sizeof(char));
if (temporary == '\n')
{
string[size] = '\0';
return string;
}
else
string[size] = temporary;
size++;
}
}
vendedor * alocarVende()
{
vendedor * tmpVende = (vendedor *)
realloc(vende, sizeof(vendedor)* vende_sz+1); //crashes here at second time
if (tmpVende == NULL)
{
printf("\nfailed to allocate.\n");
//free(tmpVende);
exit(-1);
}
else
{
vende = tmpVende;
//commented due to problems related
//free(tmpVende);
vende_sz++;
return vende;
}
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "structs.h"
#include "functions.h"
int main() {
login();
return 0;
}
bool login()
{
if (vende_sz == 0)
{
vende = alocarVende();
vende[0].salario = 666.66;
vende[0].numero = 1;
vende[0].comissao = 22;
vende[0].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[0].nome);
vende = alocarVende();
vende[1].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[1].nome);
return true;
}
}
any tips or help? I tried commenting free and some other things but still the same problem, thanks.
Edit: added more bits of code.
vende = tmpVende;
free(tmpVende);
This is precisely the same as:
vende = tmpVende;
free(vende);
Since vede and tmpVende are pointers with the same value, passing either one to free does the same thing -- frees the underlying thing they both point to.
vende[1].nome = receberString();
Thus this is a use after free that corrupts memory.
Also, you have this:
sizeof(vendedor)* vende_sz+1
Which doesn't do what you want because multiplication has higher precedence than addition.

Segmentation fault after while loop that follows malloc

I am trying to create a 2d array dynamically, then open a txt file and copy each lenient my 2d array. Then save this array back to my main. I keep running into a segmentation error. Any suggestions how to do fix this code?
BTW i think the problem stars after the 2nd time while loop occurs...
#include<stdio.h>
char **randomArrayofStrings(){
char **twoArray=null;
int rows=50;
int col=20;
i=0;
FILE *file=null;
int messageSize=50;//this is number is trivial
file = fopen("somefile.txt","r");
twoArray= malloc(rows*sizeof(char*));
for(i=0;i<col;i++)
{
twoArray[i]=malloc(rows*sizeof(char));
strcpy(twoArray[i], "some random word");
}
while(!feof(file))
{
fgets(dArray[i],messageSize, file);
strtok(dArray[i], "\n");
i++;
}
return twoArray;
}
int main(int argc, char **argv)
{
char **localArray=null;
localArray=randomArrayofStrings();
for(i=0;i<20;i++)//20 is just a random number
printf("Strings: %s", localArray[i]);
}
As I see, in your function randomArrayofStrings loop for goes through columns "i cols in your code. So, you allocate array of pointers first and consider it as cols and then in a loop you allocate rows.
And after malloc check the value that was returned and do not use the pointer if it is NULL after memory allocation.
To free allocated memory, use the inverted sequence - free all rows in a loop and than free cols once. E.g.:
for(i=0;i<col;i++){
free(twoArray[i]);
}
free(twoArray);
twoArray = NULL;
EDIT:
And also, to use malloc and free you need #include <stdlib.h>, and #include <string.h> for strcopy, int i=0; should be instead of i=0;, and correct null value for pointers is NULL.
And what is dArray? I do not see the declaration or definition? Dou you mean twoArray?
EDIT2:
The following is my version of your program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **randomArrayofStrings(){
char **twoArray=NULL;
char * ptr = NULL;
int rows=50; // this will be also message size
int cols=20;
int i=0;
FILE *file=NULL;
file = fopen("somefile.txt","r");
if( file == NULL )
return NULL;
twoArray = (char**) malloc(cols * sizeof(char*));
if(twoArray == NULL)
{
return NULL;
}
for(i=0;i<cols;i++)
{
twoArray[i] = (char*)malloc(rows*sizeof(char));
if(twoArray[i] == NULL)
return NULL;
strcpy(twoArray[i], "some random word");
}
i = 0; // reset counter
while(!feof(file))
{
fgets(twoArray[i], rows, file);
ptr = strchr(twoArray[i],'\n');
if( ptr )
*ptr = '\0';
else
twoArray[i][rows-1] = '\0';
i++;
if( i >= cols)
break;
}
fclose(file);
return twoArray;
}
void freeMy2dArray(char **twoArray, int n)
{
int i;
for(i=0; i < n; i++){
free(twoArray[i]);
}
free(twoArray);
twoArray = NULL;
}
int main(int argc, char **argv)
{
int i;
char **localArray=NULL;
localArray = randomArrayofStrings();
if( localArray == NULL )
return 1;
for(i=0;i<20;i++)//20 is just a random number
printf("Strings: %s\n", localArray[i]);
freeMy2dArray(localArray, 20);
}
You are not suppossed to free() twoArray inside randomArrayofStrings(). You have to free them inside main(), once you're done with using the allocated memeory.
That said, the way you're using sizeof(localArray) in main() is wrong. You have to use the exact value you did use to poupulate twoArray.

pointer to dynamic array of pointers to dynamic array of pointer that points to strings

i have a problem with the initialization of the values inside the first dynamic array of pointers
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
printf("allocation Failed");
return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
printf("allocation failed");
return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
printf("word number %d\n", i + 1);
*dptr[i] = GetDefinitions();
}
printf("%p",dptr);
}
i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:
Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.
i missed an allocation of something but i cant quite figure out what i missed,
thanks in advance
Your program is very broken
You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way
char ***index;
index = calloc(n, sizeof(*index));
and
char **definition;
definition = calloc(n, sizeof(*definition));
and as you see casting calloc makes it harder and it's not necessary.
You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.
They should return NULL if you want to handle failure in the caller function
return NULL;
You erroneously use the sizeof operator to determine the number of char *** pointer allocated in
int indexcount = sizeof(dptr) / sizeof(char)
this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.
You can't compute that value, you simply have to keep track of it. The size
You dereference the triple pointer twice and try to assign a double pointer to it
*dptr[i] = GetDefinitions();
here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was
dptr[i] = GetDefinitions();
This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.
Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char ***GetIndexes(unsigned int *count)
{
char ***index;
printf("please insert the number of words you want to add to dictionary > ");
scanf("%u", count);
index = calloc(*count, sizeof(*index));
if (index == NULL)
{
printf("allocation Failed");
return NULL;
}
return index;
}
char **GetDefinitions(unsigned int *count)
{
char **definition;
printf("please insert the number of defintions you want to add to the word > ");
scanf("%u", count);
definition = calloc(*count + 1, sizeof(*definition));
if (definition == NULL)
{
printf("allocation failed");
return NULL;
}
return definition;
}
int main()
{
unsigned int indexCount, i;
char ***dptr = GetIndexes(&indexCount);
if (dptr == NULL)
{
printf("memory Allocation failed");
}
for (i = 0; i < indexCount; i++)
{
unsigned int definitionsCount;
printf("Word number %u\n", i + 1);
dptr[i] = GetDefinitions(&definitionsCount);
if (dptr[i] != NULL)
{
/* use dptr[i] here or maybe somewhere else, but when you finish */
free(dptr[i]);
}
}
printf("%p", dptr);
/* now if you are done using dptr */
free(dptr);
return 0;
}
As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory
index = calloc(n, sizeof(char));
should be
index = calloc(n, sizeof(char **));
and
definition = calloc(n+1, sizeof(char));
should be
definition = calloc(n+1, sizeof(char *));

Resources