Why is the structure causing a memory error? - arrays

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct bank
{
char *name [3];
char *ha[3];
int bal[3];
};
typedef struct bank bank;
int main()
{
bank *SBI;
SBI=(bank*) malloc(sizeof(bank));
strcpy(SBI->ha[0], "1234");
printf("SUCCESS");
return 0;
}
Why is the above code generating a memory write error? When I run the code it generates some error relating to memory. I am beginner in C programming. Can anyone help me about what is wrong in the code that is causing the error.

You also need to allocate space for your three strings ha[0], ha[1], ha[2]. Your malloc allocates memory for the bank structure, including three pointers, but these pointers need to be allocated too, with malloc or strdup for example:
for (int i = 0; i < 3; i++) {
bank->ha[i] = malloc(MY_STRING_MAXLENGTH);
}
which you later free:
for (int i = 0; i < 3; i++) {
free(bank->ha[i]);
}
free(SBI);

You are copying your string into unallocated memory.
strcpy(SBI->ha[0], "1234")
Use strdup instead of strcpy. Strdup will allocate the memory for you.

Related

Convert int to string, then fill the array with the converted elements

Iam trying to fill array with numbers that i converted from int to string. The output iam trying to get is {"0", "1", "2"...} but my array is filled with the last number that i converted {"19", "19", "19"..} idk why is that. Could you please help me guys ?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *arr[20] = {};
for(int i = 0;i < 20;i++){
char str[20];
itoa(i, str, 10);
arr[i] = str;
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
}
}
Problem
char str[20]; arranges that str is a pointer to the first element of a chunk of memory containing 20 chars. Since the str is a local variable to the for loop, you cannot be sure what happens to that memory after the current iteration finishes. It is undefined behaviour.
With that in mind, think about what arr will be at the the end of the first for loop.
It will be an array of 20 pointers to some bit of memory. But you can no longer be sure what the memory contains. It may be, as in your case, that they all point to the same bit of memory, which is filled with the last string that itoa put there. This might not happen in general though.
Solution
To fix this, you should probably use malloc to allocate new memory for each string you want to keep, within the first for loop. The memory is then heap allocated, and you can be sure that each call to malloc will give you a chunk of unused memory, such that you won't be overwriting previous strings. Try for example:
for(int i = 0;i < 20;i++){
char *str = (char *) malloc(sizeof(char) * 20);
itoa(i, str, 10);
arr[i] = str;
}
Note that it is also good practice to explicitly free memory you have allocated with malloc.
char str[20]; creates a single location in memory where str is stored. It does not create a new location each time the loop is run.
arr[i] = str; points each element of arr at that one location, which by the end of the loop contains just "19".
Instead of arr[i] = str; you need to do something like strcpy(arr[i], str) to copy the current contents of str to the appropriate element of arr.
Also, as Scott Hunter pointed out, you should declare arr using char arr[20][20] to have 20 unique char arrays to actually write the strings into.
I tested the following code (changed itoa to sprintf) and it worked for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char arr[20][20] = {};
for(int i = 0;i < 20;i++){
char str[20];
sprintf(str, "%i", i);
strcpy(arr[i], str);
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
}
}
Unrolling the loop, you get
arr[0] = str;
....
arr[1] = str;
....
arr[2] = str;
.... // etc
Which is basically:
arr[0] = arr[1] = arr[2] = arr[3] (...) = str;
So yeah, they all point to the same string. There is only one str.
There's also some undefined behaviour here. Firstly, all of your pointers arr[0] etc are being dereferenced here:
printf("%s\n", arr[i]);
when the thing they point to, str, has gone out of scope, there is no guarantee what might happen when you access it. Infact, the first "instance" of str goes out of scope at the end of the first iteration of the first loop. When you assign arr[1]=str, arr[0] is techincially invalid already. However, it likely that there is just one str that remains on the stack for the duration of the function, which would be consistent with the observed behaviour, but not guaranteed.
Try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char arr[20][20] = {}; // Allocate the space to store the results
for(int i = 0;i < 20;i++){
char str[20]; // Temp store
itoa(i, str, 10);
strcpy (arr[i], str); // Copy the string from the temp store
// str goes out of scope NOW at the end of the loop, you cannot
// any pointer that points to it either outside this loop or the next time
// around the loop
}
// etc
you need to allocate memory for each place in the array, arr. you can do this on the stack or on the heap. In this approach i have allocated the strings on the heap. So i called malloc() for allocating buffers of size int (no need to allocate more).
In my approach i have used sprintf() from stdio.h to convert the numbers to string format.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_INT_DIGITS_NUM 20
int main() {
char* arr[20]; /*this is an array of 20 char pointers*/
for(int i = 0;i < 20;i++){
arr[i] = (char*)malloc(sizeof(char) * MAX_INT_DIGITS_NUM);
sprintf(arr[i], "%d", i);
}
for(int i = 0;i < 20;i++){
printf("%s\n", arr[i]);
/*now you need to free all previous allocated buffers*/
free(arr[i]);
}
return 0;
}
what is wrong with your code?
arr is only an array to char pointers! its not really holding string buffers that you can use for copy or scan to it! its only pointers that points to some address.
inside the for loop, you are declaring str buffer and you keep override it (itoa keeps copying to it) to the same place!! hence you exit the for loop in last iteration with only the last converted i!
now, just to aware you, after existing the for loop all the local variables marked by the os as released! so this can lead to memory corruption or override later in the program!
keep in mind that in my solution i always allocates MAX_INT_DIGITS_NUM bytes, no matter the i deget length. this is waste of memory! keep in mind that itoa() is not standard in C or ansi c!

Dynamically allocating array of strings

I want to dynamically allocate array of strings, but I'm not sure how I can do this. So I thought of making a struct and dynamically allocate that struct. So I made the code below, but this code creates assertion failure.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char str1[20];
char str2[20];
} String;
int main(void)
{
String * list;
list = (String *)malloc(sizeof(String));
int i = 1;
for (; i < 6; i++) {
realloc(list, i * sizeof(String));
printf("Input String 1: ");
scanf("%s", list[i - 1].str1);
printf("Input String 2: ");
scanf("%s", list[i - 1].str2);
}
for (i = 0; i < 5; i++)
printf("%s\t%s\n", list[i].str1, list[i].str2);
free(list);
}
What have I done wrong and how can I fix this problem?
Thanks :)
The man page for realloc says:
The realloc() function returns a pointer to the newly allocated
memory, which is suitably aligned for any kind of variable and may be
different from ptr, or NULL if the request fails.
The new pointer can be different from the one you passed to realloc, so you need to collect and use the pointer returned by realloc.
A structure always has the same size so with this implementation you'd be stuck with always having an array of size 2.
A way to declare an array of strings (which are themselves arrays of characters) s doing
char **string;
If you want an array of 20 strings then that'd be:
string = malloc(sizeof(char*)*20);
Structs must have constant size, so i don't think the compiler will like you trying to allocate more memory for a structure than what it was defined with.

Copying 2D arrays in C

I'm trying to copy some 2D arrays of strings into an another one.
I have 2 arrays that look like this:
char *tabA[SIZE];
char *tabB[SIZE];
I want to copy tabA[indexA] to tabB[indexB] but strcpy(tabB[indexB], tabA[indexA]) doesn't work at all, program gets crashed (but compiler doesn't return any errors).
strcpy(tabB[indexB], tabA[indexA]) doesn't work at all, program gets
crashed
Possibly because tabB[indexB] is not initialized and contain NULL or invalid pointer.
Solution
Allocate memory to tabB statically using a 2D array as char tabB[SIZE1][SIZE2] = {{0}}; or dynamically as for(i = 0; i < SIZE; ++i) tabB[i] = malloc(...); or using strdup. In case of dynamic allocation, make sure you free and don't leak the memory.
I'm using memcpy from string.h, prototyped like this:
void *memcpy(void *dest, const void *src, size_t n);
The memcpy() function copies n bytes from memory area src to memory
area dest.
For more detail read the manual of memcpy using the command man memcpy on a terminal.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const size_t SIZE=8;
int main()
{
char *data[] = {"jan", "fev", "mar", "apr", "mai", "jun", "jul", "aug"};
char *data2[SIZE];
memcpy(data2, data, sizeof(char*) * SIZE);
for (int i = 0; i < 8; ++i)
printf("data = %s, data2 = %s\n", data[i], data2[i]);
return (0);
}
tabB[indexB] = strdup(tabA[indexA]);
works perfectly :)

Why am I getting a segmentation fault when using realloc()?

This small testing program is reading strings from the command line, and I'm getting a seg fault. Can anyone help me?
I also want to ask about how is realloc() different from malloc()? I mean I think realloc() is way smarter so why do we even need malloc()? And for malloc() I know we have to copy the strings and malloc() into the new memory, but can anyone gives me an example of that?
#include <stdio.h>
#include <stdlib.h>
//reading the string from the command line
int
main(int argc, char *argv[]){
char** inputStrings;
int i;
for(i=1;i<argc;i++){
inputStrings=realloc(*inputStrings,i*sizeof(argv[i]));
inputStrings[i-1]=argv[i];
}
for(i=0;i<argc-1;i++){
printf("what is in the address: %s\n",inputStrings[i]);
}
free(inputStrings);
return 0;
}
you forgot to allocate memory to char** inputStrings;
To solve,
allocate memory to inputStrings and inputStrings[i]. [malloc()/ calloc()]
or,
allocate memory to inputStrings and set inputStrings[i] to NULL before realloc().
Check the man page of realloc().
Note: Please learn to use a debugger, like gdb. It's really helpful to pinpoint errors like the above ones.
Edit:
inputStrings=realloc(*inputStrings,i*sizeof(argv[i]));
is also wrong concept. You have to allocate memory to inputStrings and inputStrings[i] seperately. Check this answer for some help regarding this.
you should allocate the memory for that char** inputString. using the malloc or calloc first.
inputstring = malloc(sizeof(char*));
Then you should allocate the memory for each position with in the looping
inputString[i] = malloc(sizeof(char));
after that only you are able to reallocate the memory using realloc.
fixed example
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char **inputStrings = NULL;
int i;
for(i=1; i<argc; i++){
inputStrings=realloc(inputStrings, i*sizeof(argv[i]));//check omitted
inputStrings[i-1]=argv[i];
}
for(i=0;i<argc-1;i++){
printf("what is in the address: %s\n", inputStrings[i]);
}
free(inputStrings);
return 0;
}

Why this program is crashing did i wrongly allocated memory

This program is crashing. Please tell me what's wrong with it. When I use an array instead of a pointer like Name[12] in the structure it doesn't crash. I guess there is some problem in dynamic memory allocation. Help please.
#include <stdio.h>
struct struct_tag
{
int number;
char *Name;
} struct_name;
main()
{
struct_name.number = 34;
char *Name = (char *) malloc(sizeof(char));
strcpy(struct_name.Name,"A");
printf("%d", struct_name.number);
}
You're allocating a single character:
char *Name = (char *) malloc(sizeof(char));
And then never using that memory for anything. You meant to allocate memory for struct_name.Name, undoubtedly. But even if you had done so, you're then filling it with two characters ('a' and '\0'):
strcpy(struct_name.Name,"A");
which will cause an entirely different bug.
You want to say:
struct_name.Name = malloc( 2 );
Since (a) you shouldn't cast the result of malloc() and (b) sizeof(char) is always 1 and (c) you need room for the 0 at the end of your string.
For errors:
You are allocating memeory for *Name however you are not allocating
memory for struct_name.Name. So first thing is you need to allocate memory for struct_name.Name
As you already know that you'll be storing "A" in
struct_name.Name you should allocate memory for 2 char.("A" is string i.e 'A' and '\0')
For warnings:
If you want to use strcpy function include string.h in your code.
Also if you are using malloc include stdlib.h in your code.
Try this fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct struct_tag
{
int number;
char *Name;
}struct_name;
int main()
{
struct_name.number = 34;
struct_name.Name = malloc(sizeof(char)*2); // As you will store "A"
strcpy(struct_name.Name,"A");
printf("%d \t", struct_name.number);
printf("%s \n", struct_name.Name);
return 0;
}
first look code carefully.
char *Name = (char *) malloc(sizeof(char));
strcpy(struct_name.Name,"A");
Hare for what you allocated memory (char *Name) and in which you copied string(struct_name.Name)?
here you not allocate memory for struct_name.Name. Also you have allocate memory for one character and you tried to copy two characters.('A' and '\0').
It should be
struct_name.Name = malloc(2);

Resources