I'm having trouble creating a dynamic char array. This is what I have so far.
char * arr;
arr = (char*)malloc (2 * sizeof (char));
It's not allocating space for only 2 characters, it's letting me enter up to arr[8] and then giving me strange errors after 8.
I also tried making a 2 dimensional char array. The first dimension allocates correctly, but then the second dimension has more space than I allow it to have and gets an error at around 12 characters or so. Any help would be greatly appreciated. I would prefer to make a 1 dimensional dynamic array if possible.
This line arr = (char*)malloc (2 * sizeof (char)); will allocate memory for 2 bytes only. But you are overwriting the memory by accessing the more 8 or more than 8 byes. If you access more than two byes means, it will give some unpredictable issue. In case you want more memory please follow the below code.
#define USER_SIZE 10
arr = (char*)malloc ( USER_SIZE * sizeof (char));
Assign the value in USER_SIZE macro and then allocate the memory as much as you want.
Example for 2D pointer ( 5 X 10 )
#define ROW 5
#define COLUMN 10
main()
{
unsigned char **p = NULL, colum = 0;
p = malloc ( ROW * sizeof ( unsigned char *) );
for (;colum< ROW; ++colum )
{
p[colum] = malloc (COLUMN * sizeof (unsigned char ));
}
}
What you are doing is called buffer overflow by writing beyond the bounds of memory allocated by malloc call. The compiler doesn't do bounds checking (it assumes you know what you are doing, and you only pay for what you use) and allow you to compile and run. However, it will lead to undefined behaviour and your program may crash. You shouldn't rely on such behaviour.
You, the programmer, has to make sure that you don't do illegal memory access. You should not cast the result of malloc. Also, malloc can fail to allocate memory in which case it returns NULL, the null pointer, which you should take care of. You can combine the two statements into one.
int length = 8; // you can also use a macro
char *arr = malloc(length * sizeof *arr);
if(arr) {
// malloc call successful
// do stuff with arr
}
Related
I was wondering why realloc for a char* or whatever 1D array works if I do something like
oldpointer=realloc(oldpointer,newsize);
But when I try with a 2D char* array it fails.
Looking here and there I see that sometimes people use
NewPointer=realloc(oldpointer,newsize) but if it's the only use it will not be useful to me, since I need to resize the matrix' columns and rows often, in a loop (I must fill an array of strings without knowing first how many string I will insert nor the size of each one)
the code I used for trying is this,
void main(){
int max = 5, i,j;
char **matrix;
matrix=malloc(max*sizeof(char));
for(i=0;i<max;i++){
matrix[i]=malloc(max*sizeof(char));
}
matrix=realloc(matrix,max*2*sizeof(char));
strcpy(matrix[4],"we\0");
printf("%s",matrix[4]);
}
Error in `./out': realloc(): invalid next size: 0x00000000015c4010 ***
Aborted
The problem is that your double pointer can't hold pointers because you did not allocate enough space.
matrix = malloc(max * sizeof(char));
/* which is exactly the same as
* matrix = malloc(max);
*/
should be
matrix = malloc(max * sizeof(char *));
/* ^ max pointers, so sizeof a poitner */
then if you want to realloc(), you can do it like this
void *pointer;
pointer = realloc(matrix, 2 * max * sizeof(char *));
if (poitner == NULL)
handleFailure_OrExit_ButDoNot_Use_The_Realloced_Poitner();
matrix = pointer;
Always check the return value of a function if it returns one, for example malloc()/calloc()/realloc() "and any custom implementation normally", return NULL on failure.
First your matrix is an array of char*, so you should be allocating:
matrix=malloc(max * sizeof(char*));
Likewise for the realloc().
You also don't need "we\0", "we" would suffice. All strings in double quotes are NUL terminating string literals. Allocate enough memory for each of char*s and the chars and you should be good.
I have this code right here.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int *size;
int i = 0;
char buf[] = "Thomas was alone";
size = (int*)calloc(1, sizeof(buf)+1);
for(i=0; i<strlen(buf); i++)
{
*(size+i) = buf[i];
printf("%c", *(size+i));
}
free(size);
}
To my understanding calloc reserves a memspace the size of the first arg multiplied by the second, in this case 18. The length of buf is 17 and thus the for loop should not have any problems at all.
Running this program results in the expected results ( It prints Thomas was alone ), however it crashes immediately too. This persists unless I crank up the size of calloc ( like multiplied by ten ).
Am I perhaps understanding something wrongly?
Should I use a function to prevent this from happening?
int *size means you need:
size = calloc(sizeof(int), sizeof(buf));
You allocated enough space for an array of char, but not an array of int (unless you're on an odd system where sizeof(char) == sizeof(int), which is a theoretical possibility rather than a practical one). That means your code writes well beyond the end of the allocated memory, which is what leads to the crashing. Or you can use char *size in which case the original call to calloc() is OK.
Note that sizeof(buf) includes the terminal null; strlen(buf) does not. That means you overallocate slightly with the +1 term.
You could also perfectly sensibly write size[i] instead of *(size+i).
Change the type of size to char.
You are using an int and when you add to the pointer here *(size+i), you go out of bounds.
Pointer arithmetic takes account of the type, which in you case is int not char. sizeof int is larger than char on your system.
You allocate place for char array not for int array:
char is 1 byte in memory (most often)
int is 4 bytes in memory (most often)
so you allocate 1 * sizeof(buf) + 1 = 18 bytes
so for example in memory:
buf[0] = 0x34523
buf[1] = 0x34524
buf[2] = 0x34525
buf[3] = 0x34526
but when you use *(size + 1) you don't move pointer on 1 byte but for sizeof(int) so for 4 bytes.
So in memory it will look like:
size[0] = 0x4560
size[1] = 0x4564
size[2] = 0x4568
size[3] = 0x4572
so after few loops you are out of memory.
change calloc(1, sizeof(buf) + 1); to calloc(sizeof(int), sizeof(buf) + 1); to have enough memory.
Second think, I think is some example on which you learn how it works?
My suggestion:
Use the same type of pointer and variable.
when you assign diffnerent type of variables, use explicit conversion, in this example
*(size+i) = (int)buf[i];
I have to maintain an array of strings, which each string will contain the IP address of a neighbor. For some reason i need to maintain them as strings.
typedef struct _neighbors
{
int num_neigbors;
char **neighbor_address;
} neighbors;
Assume i have two neighbors to add.
I view char ** neighbor_address as an array of char * pointers.
I understand that i need to malloc memory for neighbor_address[0] and neighbor_address[1] to store their IP addresses. Since the IP address is of form "x.y.z.w" i will be doing a malloc of 7*sizeof (char).
My doubt is how much memory should i allocate for the base char **neighbor_address. Should it be 4 bytes so that it can store the IP address of the base pointer of neighbor_address[0]?
I say this because i get a SIGSEGV (Segmentation fault) if i don't do a malloc as follows:
neighbor_address = malloc (1, sizeof (char *));
Anything that i am missing?
You should not do malloc like this-
neighbor_address = malloc (1, sizeof (char *));
you are not following the syntax of malloc here. It is the syntax of calloc. If you are using calloc you can use this method-
neighbor_address = calloc (n, sizeof (char *));
If you want to use malloc Try the following changes-
neighbor_address = (char **)malloc (n * sizeof (char *));
for(i=0;i<n;i++)
neighbor_address[i] = (char *)malloc (8 * sizeof (char));
But You are using structure here. So you need to use arrow operator to allocate memory for char **neighbor_address; because it is a pointer type. Try this-
neighbors -> neighbor_address = (char **)malloc (n * sizeof (char *)); // n -> no of ip addresses
for(i=0;i<n;i++)
neighbors -> neighbor_address[i] = (char *)malloc (8 * sizeof (char));
Oh, I think you didn't understand the max length of an IP Address.
It could be 3 digits between every dot so it can be 255.255.255.255 at maximum.
So the code to dynamically allocate memory for it would be so:
#define MAX_IP strlen("255.255.255.255")
int i;
neighbors my_neighbors;
my_neighbors.num_neighbors = ?; //Some value that is the num of IP Addresses needed to be stored.
my_neighbors.neighbor_address = malloc(sizeof(char*)*my_neighbors.num_neighbors); //allocate a char* (that is about to be a string) for each neighbor.
for(i = 0 ; i < my_neighbors.num_neighbors ; i++)
{
my_neighbors.neighbor_address[i] = malloc(sizeof(char)*(MAX_IP+1)); //Allocating enough room in each IP string for 255.255.255.255 + '\0' (null).
}
//Doing some stuff.
//Freeing memory:
for(i = 0 ; i < my_neighbors.num_neighbors ; i++)
{
free(my_neighbors.neighbor_address[i]);
}
free(my_neighbors.neighbor_address);
And that's it.
Hope you understood.
You can allocate the memory like this.
neighbor_address = (char**)malloc(num_neighbors * sizeof(char*));
for(i=0; i<num_neighbors; ++i) {
neighbor_address[i] = (char*)malloc(len_of_address);
}
Make sure that 'len_of_address' is large enough to store all characters (including the terminating '\0' character if you plan to store \0-terminated strings).
Be aware of the fact that you need more space than 1 character per fragment of the ip address if it is a number larger than 9.
So to store 196.168.0.3 you would need at least 12 characters.
First, two things: sizeof(char) is 1, regardless of the implementation. And I think you misunderstood malloc prototype. It takes the number of bytes you want to allocate, and it returns the allocated pointer.
If you want to store x IPs, then you'll have to do:
neighbor_address = malloc(x * sizeof(char*));
And then if you want to store 7 chars in each string, you'll have to do:
for (i = 0; i < x; i++)
neighbor_adress[i] = malloc(7 + 1); // 7 chars plus '\0' character
You must allocate memory for an array of num_neighbors char pointers. But most of all, remember to # include <stdlib.h> : you called malloc with wrong parameters, and that's probably what caused the segfault before a wrong size.
The least error-prone pattern for using malloc is this one :
neighbor_address = malloc(num_neighbors * sizeof *neighbor_address);
Just put the same variable as left operand of = and operand of sizeof, and adjust the number of elements.
I am coding a program which takes a text file as an input, makes the index of the words of it and prints the output(the index) in a file and in the screen.
the input file may be huge. but we KNOW that the maximum variety of the words used in the text file is 200. we don't know what's the maximum of lines and characters of each word. so I should reserve a large number for them. I took the maximum of line 1000 and the maximum characters of each word 100.
I am programming in Turbo C and (I am forced to use that). the compiler allocates just 64kb memory (with the size of the compiler included) and so I have to use MALLOC.
my program is supposed to work in this algorithm:
it reads the input file line by line with fgets. then in the current line, it reads word by word with strtok. so far I have the xth word in yth line. I want to put the words in an array of pointers. so I need a char * word[200]. and I want to show how many times, which word is repeated in which line. so I need a int index [200][1000]. if in yth line, the xth word is existed I would do index[x][y]++.
so now I need to allocate MALLOC memory to these char * word[200] and int index[200][1000] . Can anyone help? I tried all the answers to these question and none of them helped.
You don't quite have malloc right. Your malloc(100) is only allocating 100 bytes. You need
char * words[i] = malloc(sizeof(char *) * 100);
This allocates 800 bytes (100 elements of 8 bytes (size of a pointer) each).
Similarly, in the second malloc, you want two integers, you need
int index[i][j] = malloc(sizeof(int *) * 2);
You shouldn't cast to a pointer; it returns a void pointer, which is implicitly cast to whatever type of pointer you need just by virtue of the assignment.
http://www.cplusplus.com/reference/cstdlib/malloc/
FURTHERMORE:
Additionally, you're trying to stuff 2 bytes into an integer pointer or 4 bytes (100-96 = 4; the 96 is 8 * 12) into a character pointer. I have no idea in the world what that will do. The BEST you can hope for is that you'll just lose the memory somewhere and effectively have 12 character pointers and 2 memory leaks.
If I understand you
In the first loop, I want to define an array of 200 pointers that each pointer, points to an array of char blocks. I want each pointer, points to an array of maximum 100 bytes. Meaning 100 char blocks
char **words = NULL;
int i;
words = malloc(sizeof(char*) * 200);
for(i = 0; i < 200; i++) {
words[i] = malloc(100);
}
There's allocating 200 words with 100 bytes size here.
In the second loop, I want to define a 2D array of int blocks that each block is maximum 2 bytes. meaning 200 * 1000 int blocks.
int **index = NULL;
int i;
index = malloc(sizeof(int*) * 200)
for (i = 0; i < 200; i++) {
index[i] = malloc(sizeof(int) * 1000);
}
Here you allocate 200x1000 int array.
char * words = malloc(200*100);
int * index = malloc(200*1000*sizeof(int));
// word[i*200+j] : character j in word i
// index[i*200+j] : int at index i,j
alternatives:
// mallocing an array for storing a maximum of 200 malloced words
char ** words = malloc(200*sizeof(char*));
// adding a new word, at index i, which is pointed to by pszNewWord (null terminated)
words[i] = strdup(pszNewWord);
I'm trying to allocate memory for a multidimensional array (8 rows, 3 columns).
Here's the code for the allocation (I'm sure the error is clear for you)
char **ptr = (char **) malloc( sizeof(char) * 8);
for (i = 0; i < 3; i++)
ptr[i] = (char *) malloc( sizeof(char) * 3);
The crash happens when I reference this:
ptr[3][0];
Unhandled exception at 0x0135144d in
xxxx.exe:
0xC0000005: Access violation writing
location 0xabababab.
Are there any recommended references/readings for this kind of subject?
Thanks.
The first malloc() is wrong. It should be:
malloc(sizeof(char*) * 8)
A char* is 4 byte (or 8 byte... see P.S) whereas char is 1 byte. When you write ptr[3] the compiler will assume that you want to access to the base address of ptr + 3*sizeof(char*). So you will access to memory that you didn't allocate.
P.S:
To be more precise, char* is 4 byte on 32 bit systems and 8 byte on 64 bit systems.
I don't know offhand any books on memory allocation, but any introductory C tutorial should explain it. As for your bug, your for loop only initializes the first 3 rows, instead of the 8 you allocated. It should be:
for (i = 0; i < 8; i++)
char **ptr = (char **) malloc( sizeof(char *) * 8);
Before, you were allocating space for 8 chars. You want space for 8 pointers to char.
Michael pointed out the other error, writing the first char from a string you never allocated.
It may help if you use constants, like:
const int STRING_COUNT = 8;
const int STRING_LEN = 2;
char **ptr = (char **) malloc( sizeof(char *) * STRING_COUNT);
ptr is an array of 8 pointers, not chars, so the first line should be:
char **ptr = (char **) malloc( sizeof(char*) * 8)
Because there are 8 pointers, the loop should go from 0 to 7:
for (i = 0; i < 8; i++)
You can also consider using a less prone to errors version of the first line:
char **ptr = (char **) malloc( sizeof(*ptr) * 8)
And the last one:
ptr[i] = (char *) malloc( sizeof(*ptr[i]) * 3);
The rule is: always take sizeof of dereferenced lvalue. If lvalue is ptr, then you need sizeof(*ptr). ptr[i] becomes sizeof(*ptr[i]).
There are several errors/inconsistencies in your code, but the first major one is the wrong sizeof in the first allocation. The error that you made could have easily been avoided if you followed some good-practice guidelines:
(1) As much as possible avoid using type names in statements. Type names belong in declarations, not in statements.
(2) Don't cast the result of memory allocation functions.
The first allocation should have looked as follows
char **ptr = malloc( 8 * sizeof *ptr );
Try to remember this as a generic pattern: malloc requestes should normally look as follows
pointer = malloc( count * sizeof *pointer );
Note: no type names are mentioned in the above statement.
Of course, you should also make up your mind about the first size of your 2D array. You attempt to allocate 8, then you only initialize 3. Why?
There are two problems.
First, as others have pointed out, your initial malloc should be
malloc(sizeof(char *) * 8)
Second, you are initializing the first three elements in the 8-element array, but ptr[3][0] refers to the fourth element. Thus the crash.