I am having trouble with the allocating memory part of my program. I am supposed to read in a file that contains a list of names then allocate memory for them and store them in the allocate memory. This is what I have so far, but I keep getting a segmentation fault when I run it.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING_LEN 25
void allocate(char ***strings, int size);
int main(int argc, char* argv[]){
char **pointer;
int size = atoi(argv[1]);
allocate(&pointer, size);
}
/*Will allocate memory for an array of char
pointers and then allocate those char pointers with the size of MAX_STRING_LEN.*/
void allocate(char ***strings, int size){
**strings = malloc( sizeof (char) * MAX_STRING_LEN);
}
This is currently not working because I am given a seg fault. Thanks a lot for the help in advance.
void allocate(char ***strings, int size)
{
int i;
// Here you allocate "size" string pointers...
*strings = malloc( sizeof (char*) * size);
// for each of those "size" pointers allocated before, here you allocate
//space for a string of at most MAX_STRING_LEN chars...
for(i = 0; i < size; i++)
(*strings)[i] = malloc( sizeof(char) * MAX_STRING_LEN);
}
So, if you pass size as 10...
In your main you will have space for 10 strings (pointer[0] to pointer[9]).
And each of those strings can have up to 24 characters (don't forget the null terminator)...
Pointers are a little tricky but here is a trick to deal with them:
Lets say you have your main like this:
int main()
{
int ***my_variable;
}
and you know how to operate in my_variable inside main...
To use it in a function you do as following:
add an extra * in the parameter
void f(int ****my_param)
and whenever you want to use it inside the function, use the same way as you would use in main with this little change:
(*my_param) = //some code
by using (*my_param) is the same as if you were using to my_variable in main
You need
*strings = malloc(sizeof(char *) * 10); // Here is the array
(*strings)[0] = malloc(MAX_STRING_LEN);
strcpy((*strings)[0], "The first person");
printf("First person is %s\n", (*strings)[0]);
Dunno where size comes in
Related
In the main function, I use malloc() to create an unsigned char array:
int main()
{
int length = 64;
unsigned char *array = (unsigned char *)malloc(length * sizeof(unsigned char));
...
change_size(array, length);
}
change_size() defined in .h:
void change_size(unsigned char* arr, int len);
In the change_size function, I will use realloc() to increase the array size:
void change size(unsigned char* arr, int len)
{
printf("%d\n", len);
len = len + 16;
printf("%d\n", len);
arr = (unsigned char *)realloc(arr, len * sizeof(unsigned char));
int new_len = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", new_len);
}
The printf() show me:
64
80
8
The array size in the main() also needs to be updated.
Then how to change this array size correctly?
You need to pass your parameters as pointers if you want to change their value back in the caller. That also means you pass your array pointer as a pointer, because realloc might change it:
int change_size(unsigned char **arr, int *len)
{
int new_len = *len + 16;
unsigned char *new_arr = realloc(*arr, new_len);
if (new_arr) {
*len = new_len;
*arr = new_arr;
}
return new_arr != NULL;
}
Here I've modified change_size to suit, and also added a return value to indicate success, since realloc can fail to resize the memory. For clarity, I removed the printf calls. Oh, and I also removed the cast, since that is not valid in C.
Example usage:
if (!change_size(&array, &len))
{
perror("change_size failed");
}
One final note is that you can use your change_size function for the first allocation too, rather than calling malloc. If the first argument to realloc is NULL, it does the same thing as malloc.
First C is not babysitter language,
You only need basic things then you can do everything,
Just try hard to totally understand basic.
#include <stdio.h>
#include <stdlib.h>
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
free(G1);
return 0;
}
Okay I answer it. #Chipster
#include <stdio.h>
#include <stdlib.h>
int change_size(char** arr, int len)
{
char* nar=(char*)malloc(sizeof(char)*(len+16));
if(nar){
free(* arr);
*arr=nar;
nar[10]='K';//this will let you know its right
return len+16;
}
return len;
}
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
printf("%d\n",G1);
G1_Len=change_size(&G1,G1_Len);
printf("%c\n",G1[10]);
printf("%d\n",G1);
printf("%d\n",G1_Len);
free(G1);
return 0;
}
I am working on a project in which I have to create an array of string (char *), however, when I try to free the array of array, "double free or corruption" is given and I couldn't figure out the problem.
The code extraction here is a simplified version, it may seem meaningless but it illustrates the problem I am facing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char **cptr;
int i;
cptr = malloc(256*sizeof(char));
for (i=0; i<256; i++) {
cptr[i] = calloc(2, sizeof(char));
cptr[i][0] = (char)i;
}
for (i=0; i<256; i++) {
free(cptr[i]);
}
free(cptr);
return 0;
}
Thank you.
cptr = malloc(256 * sizeof(char));
Above line is wrong. Even if you compute number of bytes allocated above, it is 256 bytes. If size of pointer is 4 bytes on your machine, it would be enough for 64 pointers. Instead you need 256 pointers. Use
cptr = malloc(256 * sizeof(char *));
Im writing a fairly simple program to read a file line by line and store it into an array of lines, my program compiles fine but it crashes everytime I run it.
This is my code:
#include <stdio.h>
#include <string.h>
#define LINESIZE 512
typedef struct {
char **data;
size_t nused;
} lines_t;
lines_t readlines(FILE *fp);
int main(int argc,char* argv[]) {
FILE *fp;
(void)argc;
if((fp = fopen(argv[1],"r+")) == 0) {
perror("fopen");
}
readlines(fp);
return 0;
}
lines_t readlines(FILE *fp) {
lines_t line_data;
char line[LINESIZE];
char temp[20];
int num_lines = 0;
(*line_data.data) = (char *)malloc(LINESIZE);
while(fgets(line,LINESIZE,fp)) {
sscanf(line,"%s\n",temp);
strcpy(line_data.data[num_lines], temp); /* Program crashes here */
num_lines++;
}
return line_data;
}
The line where I try to copy my array is giving me trouble, So my question is, How do I copy my character array temp into the char **data inside struct lines_t if I am not doing it right?
You are dereferencing an invalid pointer here:
(*line_data.data) = (char *)malloc(15);
line_data.data is a char **. You are trying to deference it but it is not yet set to any meaningful value. You need to allocate memory for line_data.data before you allocate memory for *line_data.data.
(char *)malloc(15) is particularly suspicious also. Where does 15 come from and what are you actually allocating memory for? Casting the result of malloc is generally considered bad practice, and in your case, rightly so, because malloc is declared in stdlib.h and you aren't including that header. If you want to allocate enough space to hold 15 char *, then use malloc(15 * sizeof(char *)) or alternatively, malloc(15 * sizeof(*line_data.data)) (here it is safe to use *line_data.data even if it doesn't point to anything, because sizeof does not evaluate its operand).
You can try malloc line_data.data before strcpy.
lines_t readlines(FILE *fp) {
lines_t line_data;
line_data.data = malloc(LINESIZE);
*line_data.data = malloc(LINESIZE);
return line_data;
}
You first need to allocate memory.
You need to allocate both for the array of strings and string array. Here you need to have an upper limit while calling a malloc.
line_data = malloc(10* sizeof(char*)); // for example here the upper limit is 10
while(fgets(line,LINESIZE,fp)) {
sscanf(line,"%s\n",temp);
line_data.data[num_lines] = malloc(sizeof(char) * (strlen(temp)+1));
strcpy(line_data.data[num_lines], temp); /* Program crashes here */
num_lines++;
}
I know how to create an array of structs but with a predefined size. However is there a way to create a dynamic array of structs such that the array could get bigger?
For example:
typedef struct
{
char *str;
} words;
main()
{
words x[100]; // I do not want to use this, I want to dynamic increase the size of the array as data comes in.
}
Is this possible?
I've researched this: words* array = (words*)malloc(sizeof(words) * 100);
I want to get rid of the 100 and store the data as it comes in. Thus if 76 fields of data comes in, I want to store 76 and not 100. I'm assuming that I don't know how much data is coming into my program. In the struct I defined above I could create the first "index" as:
words* array = (words*)malloc(sizeof(words));
However I want to dynamically add elements to the array after. I hope I described the problem area clearly enough. The major challenge is to dynamically add a second field, at least that is the challenge for the moment.
I've made a little progress however:
typedef struct {
char *str;
} words;
// Allocate first string.
words x = (words) malloc(sizeof(words));
x[0].str = "john";
// Allocate second string.
x=(words*) realloc(x, sizeof(words));
x[1].FirstName = "bob";
// printf second string.
printf("%s", x[1].str); --> This is working, it's printing out bob.
free(x); // Free up memory.
printf("%s", x[1].str); --> Not working since its still printing out BOB even though I freed up memory. What is wrong?
I did some error checking and this is what I found. If after I free up memory for x I add the following:
x=NULL;
then if I try to print x I get an error which is what I want. So is it that the free function is not working, at least on my compiler? I'm using DevC??
Thanks, I understand now due to:
FirstName is a pointer to an array of char which is not being allocated by the malloc, only the pointer is being allocated and after you call free, it doesn't erase the memory, it just marks it as available on the heap to be over written later. – MattSmith
Update
I'm trying to modularize and put the creation of my array of structs in a function but nothing seems to work. I'm trying something very simple and I don't know what else to do. It's along the same lines as before, just another function, loaddata that is loading the data and outside the method I need to do some printing. How can I make it work? My code is as follows:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words *, int *);
main()
{
words *x;
int num;
LoadData(&x, &num);
printf("%s %s", x[0].str1, x[0].str2);
printf("%s %s", x[1].str1, x[1].str2);
getch();
}//
void LoadData(words *x, int * num)
{
x = (words*) malloc(sizeof(words));
x[0].str1 = "johnnie\0";
x[0].str2 = "krapson\0";
x = (words*) realloc(x, sizeof(words)*2);
x[1].str1 = "bob\0";
x[1].str2 = "marley\0";
*num=*num+1;
}//
This simple test code is crashing and I have no idea why. Where is the bug?
You've tagged this as C++ as well as C.
If you're using C++ things are a lot easier. The standard template library has a template called vector which allows you to dynamically build up a list of objects.
#include <stdio.h>
#include <vector>
typedef std::vector<char*> words;
int main(int argc, char** argv) {
words myWords;
myWords.push_back("Hello");
myWords.push_back("World");
words::iterator iter;
for (iter = myWords.begin(); iter != myWords.end(); ++iter) {
printf("%s ", *iter);
}
return 0;
}
If you're using C things are a lot harder, yes malloc, realloc and free are the tools to help you. You might want to consider using a linked list data structure instead. These are generally easier to grow but don't facilitate random access as easily.
#include <stdio.h>
#include <stdlib.h>
typedef struct s_words {
char* str;
struct s_words* next;
} words;
words* create_words(char* word) {
words* newWords = malloc(sizeof(words));
if (NULL != newWords){
newWords->str = word;
newWords->next = NULL;
}
return newWords;
}
void delete_words(words* oldWords) {
if (NULL != oldWords->next) {
delete_words(oldWords->next);
}
free(oldWords);
}
words* add_word(words* wordList, char* word) {
words* newWords = create_words(word);
if (NULL != newWords) {
newWords->next = wordList;
}
return newWords;
}
int main(int argc, char** argv) {
words* myWords = create_words("Hello");
myWords = add_word(myWords, "World");
words* iter;
for (iter = myWords; NULL != iter; iter = iter->next) {
printf("%s ", iter->str);
}
delete_words(myWords);
return 0;
}
Yikes, sorry for the worlds longest answer. So WRT to the "don't want to use a linked list comment":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char** words;
size_t nWords;
size_t size;
size_t block_size;
} word_list;
word_list* create_word_list(size_t block_size) {
word_list* pWordList = malloc(sizeof(word_list));
if (NULL != pWordList) {
pWordList->nWords = 0;
pWordList->size = block_size;
pWordList->block_size = block_size;
pWordList->words = malloc(sizeof(char*)*block_size);
if (NULL == pWordList->words) {
free(pWordList);
return NULL;
}
}
return pWordList;
}
void delete_word_list(word_list* pWordList) {
free(pWordList->words);
free(pWordList);
}
int add_word_to_word_list(word_list* pWordList, char* word) {
size_t nWords = pWordList->nWords;
if (nWords >= pWordList->size) {
size_t newSize = pWordList->size + pWordList->block_size;
void* newWords = realloc(pWordList->words, sizeof(char*)*newSize);
if (NULL == newWords) {
return 0;
} else {
pWordList->size = newSize;
pWordList->words = (char**)newWords;
}
}
pWordList->words[nWords] = word;
++pWordList->nWords;
return 1;
}
char** word_list_start(word_list* pWordList) {
return pWordList->words;
}
char** word_list_end(word_list* pWordList) {
return &pWordList->words[pWordList->nWords];
}
int main(int argc, char** argv) {
word_list* myWords = create_word_list(2);
add_word_to_word_list(myWords, "Hello");
add_word_to_word_list(myWords, "World");
add_word_to_word_list(myWords, "Goodbye");
char** iter;
for (iter = word_list_start(myWords); iter != word_list_end(myWords); ++iter) {
printf("%s ", *iter);
}
delete_word_list(myWords);
return 0;
}
If you want to dynamically allocate arrays, you can use malloc from stdlib.h.
If you want to allocate an array of 100 elements using your words struct, try the following:
words* array = (words*)malloc(sizeof(words) * 100);
The size of the memory that you want to allocate is passed into malloc and then it will return a pointer of type void (void*). In most cases you'll probably want to cast it to the pointer type you desire, which in this case is words*.
The sizeof keyword is used here to find out the size of the words struct, then that size is multiplied by the number of elements you want to allocate.
Once you are done, be sure to use free() to free up the heap memory you used in order to prevent memory leaks:
free(array);
If you want to change the size of the allocated array, you can try to use realloc as others have mentioned, but keep in mind that if you do many reallocs you may end up fragmenting the memory. If you want to dynamically resize the array in order to keep a low memory footprint for your program, it may be better to not do too many reallocs.
This looks like an academic exercise which unfortunately makes it harder since you can't use C++. Basically you have to manage some of the overhead for the allocation and keep track how much memory has been allocated if you need to resize it later. This is where the C++ standard library shines.
For your example, the following code allocates the memory and later resizes it:
// initial size
int count = 100;
words *testWords = (words*) malloc(count * sizeof(words));
// resize the array
count = 76;
testWords = (words*) realloc(testWords, count* sizeof(words));
Keep in mind, in your example you are just allocating a pointer to a char and you still need to allocate the string itself and more importantly to free it at the end. So this code allocates 100 pointers to char and then resizes it to 76, but does not allocate the strings themselves.
I have a suspicion that you actually want to allocate the number of characters in a string which is very similar to the above, but change word to char.
EDIT: Also keep in mind it makes a lot of sense to create functions to perform common tasks and enforce consistency so you don't copy code everywhere. For example, you might have a) allocate the struct, b) assign values to the struct, and c) free the struct. So you might have:
// Allocate a words struct
words* CreateWords(int size);
// Assign a value
void AssignWord(word* dest, char* str);
// Clear a words structs (and possibly internal storage)
void FreeWords(words* w);
EDIT: As far as resizing the structs, it is identical to resizing the char array. However the difference is if you make the struct array bigger, you should probably initialize the new array items to NULL. Likewise, if you make the struct array smaller, you need to cleanup before removing the items -- that is free items that have been allocated (and only the allocated items) before you resize the struct array. This is the primary reason I suggested creating helper functions to help manage this.
// Resize words (must know original and new size if shrinking
// if you need to free internal storage first)
void ResizeWords(words* w, size_t oldsize, size_t newsize);
In C++, use a vector. It's like an array but you can easily add and remove elements and it will take care of allocating and deallocating memory for you.
I know the title of the question says C, but you tagged your question with C and C++...
Another option for you is a linked list. You'll need to analyze how your program will use the data structure, if you don't need random access it could be faster than reallocating.
Your code in the last update should not compile, much less run. You're passing &x to LoadData. &x has the type of **words, but LoadData expects words* . Of course it crashes when you call realloc on a pointer that's pointing into stack.
The way to fix it is to change LoadData to accept words** . Thi sway, you can actually modify the pointer in main(). For example, realloc call would look like
*x = (words*) realloc(*x, sizeof(words)*2);
It's the same principlae as in "num" being int* rather than int.
Besides this, you need to really figure out how the strings in words ere stored. Assigning a const string to char * (as in str2 = "marley\0") is permitted, but it's rarely the right solution, even in C.
Another point: non need to have "marley\0" unless you really need two 0s at the end of string. Compiler adds 0 tho the end of every string literal.
For the test code: if you want to modify a pointer in a function, you should pass a "pointer to pointer" to the function. Corrected code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words**, int*);
main()
{
words **x;
int num;
LoadData(x, &num);
printf("%s %s\n", (*x[0]).str1, (*x[0]).str2);
printf("%s %s\n", (*x[1]).str1, (*x[1]).str2);
}
void LoadData(words **x, int *num)
{
*x = (words*) malloc(sizeof(words));
(*x[0]).str1 = "johnnie\0";
(*x[0]).str2 = "krapson\0";
*x = (words*) realloc(*x, sizeof(words) * 2);
(*x[1]).str1 = "bob\0";
(*x[1]).str2 = "marley\0";
*num = *num + 1;
}
Every coder need to simplify their code to make it easily understood....even for beginners.
So array of structures using dynamically is easy, if you understand the concepts.
// Dynamically sized array of structures
#include <stdio.h>
#include <stdlib.h>
struct book
{
char name[20];
int p;
}; //Declaring book structure
int main ()
{
int n, i;
struct book *b; // Initializing pointer to a structure
scanf ("%d\n", &n);
b = (struct book *) calloc (n, sizeof (struct book)); //Creating memory for array of structures dynamically
for (i = 0; i < n; i++)
{
scanf ("%s %d\n", (b + i)->name, &(b + i)->p); //Getting values for array of structures (no error check)
}
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
scanf ("%d\n", &n); //Get array size to re-allocate
b = (struct book *) realloc (b, n * sizeof (struct book)); //change the size of an array using realloc function
printf ("\n");
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
return 0;
}
If you want to grow the array dynamically, you should use malloc() to dynamically allocate some fixed amount of memory, and then use realloc() whenever you run out. A common technique is to use an exponential growth function such that you allocate some small fixed amount and then make the array grow by duplicating the allocated amount.
Some example code would be:
size = 64; i = 0;
x = malloc(sizeof(words)*size); /* enough space for 64 words */
while (read_words()) {
if (++i > size) {
size *= 2;
x = realloc(sizeof(words) * size);
}
}
/* done with x */
free(x);
Here is how I would do it in C++
size_t size = 500;
char* dynamicAllocatedString = new char[ size ];
Use same principal for any struct or c++ class.
I am currently trying to learn C and I have come to a problem that I've been unable to solve.
Consider:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ELEMENTS 5
void make(char **array, int *array_size) {
int i;
char *t = "Hello, World!";
array = malloc(ELEMENTS * sizeof(char *));
for (i = 0; i < ELEMENTS; ++i) {
array[i] = malloc(strlen(t) + 1 * sizeof(char));
array[i] = strdup(t);
}
}
int main(int argc, char **argv) {
char **array;
int size;
int i;
make(array, &size);
for (i = 0; i < size; ++i) {
printf("%s\n", array[i]);
}
return 0;
}
I have no idea why the above fails to read back the contents of the array after creating it. I have literally spent an hour trying to understand why it fails but have come up empty handed. No doubt it's something trivial.
Cheers,
You need to pass the address of "array" into the function. That is, you need char ***. This is because you need to change the value of array, by allocating memory to it.
EDIT: Just to make it more complete, in the function declaration you need to have something like
void make(char ***array, int *array_size)
Then you need to call it using
make(&array, &size);
Inside the function make, allocate memory with
*array = malloc(ELEMENTS * sizeof(char *));
And change other places accordingly.
Also, as kauppi has pointed out, strdup will allocate memory for you, so you don't need to do malloc on each string.
Here is the working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ELEMENTS 5
void make(char ***array) {
char *t = "Hello, World!";
*array = malloc(ELEMENTS * sizeof(char *));
int i;
for (i = 0; i < ELEMENTS; ++i) {
(*array)[i] = strdup(t);
}
}
int main(int argc, char **argv) {
char **array;
make(&array);
int i;
for (i = 0; i < ELEMENTS; ++i) {
printf("%s\n", array[i]);
free(array[i]);
}
free(array);
return 0;
}
As the other have posted - there was unused size, and strdup allocates memory by itself, and it is nice to free the memory afterwards...
See PolyThinker's comment which is absolutely spot on.
In addition to the way you pass the array, you should check a few other issues:
Perhaps you should assign something to array_size in make(...)?
strdup(char*) allocates memory, the malloc for array[i] is not necessary.
You should free all the memory you allocate after you don't need it anymore.
You are passing the current value of array to make as a copy (on the stack). when you change array in make(), you're only changing the copy, not the actual variable. Try passing by reference with &, or make it a char *** and work with *array = ...
size is declared but gets no value assigned (that should happen in function make, I suppose).