I am trying to learn dynamic memory allocation and structures and I have some questions.
First of all
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int *number;
number = malloc(1*sizeof(int));
int a;
for(a=0;a<150;a++)
{
number[a]=a;
printf("%d ",number[a]);
}
return 0;
}
In this sample I planned it to give me error. Because I allocated it to size of 1 integer, then I wrote it way too much integers. Shouldn't it give me an error? Can you explain this with detail please?
struct people
{
char *name;
int age;
char *personalInfo;
} human[3];
When I define a structure like this, how can I allocate it to keep more than 3 human? How can I change it to something like human[20] or more? In case if the answer is writing *human instead of human[3], how should I allocate it? Like malloc(number*sizeof(char)*sizeof(int)*sizeof(char))?
And one more thing, in second example do I need to allocate name and personalInfo pointers?
In this sample i planned it to give me error.
You can't "plan to give an error". You're correct to say that the code is wrong because you are writing past the end of the array, but C has no bounds checking -- accessing the array is simply undefined behavior, which means that it can do literally anything -- it can pretend to work fine or it can crash, or it can cause demons to fly out of your nose.
How can i change it to something like human[20] or more?
Well... that's exactly how:
struct people {
// members here
} human[20];
I don't see why the number "3" is so special. If you want to allocate memory dynamically, you would do it the way you would do in the case of every other data type: use the sizeof operator:
struct people *human = malloc(sizeof(human[0]) * number_of_people);
or
struct people *human = malloc(sizeof(struct people) * number_of_people);
C does not provide compile-time or run-time bounds checking of arrays. The program must perform its own bound checking. If you write beyond the end of an array, your program will have undefined behavior. In practice it means that you're corrupting your process' memory by writing to uninitialized areas or areas that are used by allocators for bookkeeping. This can cause the program to crash immediately, crash on exit, or can overwrite the values of other (possibly unrelated) variables in the heap.
To allocate a variable number of people structures, you can do this:
struct people *humans;
humans = malloc(N * sizeof(struct people));
// humans now points to an array of N `people`
For your last question, yes, you must allocate space for those strings, unless you're simply using those pointers to point to strings defined/allocated elsewhere. Note this means that even in the code above where I allocate N objects, I still haven't allocated any space for the strings, and can't write to them until I do so.
struct people
{
char *name;
int age;
char *personalInfo;
};
struct people *human;
human = malloc(sizeof(*human) * 20);
In this sample i planned it to give me error. because i allocated it to size of 1 integer, then i wrote it way too much integers. Shouldn't it give me an error? Can you explain this with detail please?
No, it shouldn't. This is undefined behavior, which may lead to a crash at runtime, but the compiler will neither warn you about it nor produce any errors. You can detect errors like this by running your program in a memory profiler, such as valgrind.
When i define a structure like this, How can i allocate it to keep more than 3 human? How can i change it to something like human[20] or more?
Like this:
struct people *human = malloc(20 * sizeof(struct people));
Like malloc( number*sizeof(char)*sizeof(int)*sizeof(char) ) ?
Besides being too inconvenient, adding up sizes of individual fields may not produce the correct size, because the compiler is allowed to pad your struct to optimize access to its fields. That is why you need to use sizeof(struct people).
The first example invokes undefined behavior.
ยง6.5.6/8: If both the pointer operand and the result point to elements of the same array
object, or one past the last element of the array object, the evaluation shall not
produce an overflow; otherwise, the behavior is undefined
If you want to allocate for 20 humans, you can do...
typedef struct people
{
char *name;
int age;
char *personalInfo;
}People;
People *human;
human = malloc(sizeof(*human) * 20);
Related
I have a pointer to char pointer in a struct. so there is a struct poiter object that I will pass to thread but thats not relevant.
so this is my struct
struct shard
{
sem_t *semaphore_o;
char **input;
char **image_o;
};
I am creating object like
struct shard *obj=malloc(sizeof(struct shard));
and I am allocating the input in shard struct
*(obj->input)=malloc(sizeof(char)+1);
but abocve line giving segFault
*(obj->input) dereferences input before input points to valid memory, invoking undefined behavior, where manifesting with a segfault is common. You first have to malloc memory for it before dereferencing. You don't provide enough details about what you're trying to do, but something like:
struct shard *obj=malloc(sizeof(struct shard));
if (obj == NULL)
{
// handle error how you want, and make a check like this for every malloc
exit(-1);
}
obj->input = malloc(howManyCharPtrsYouWant * sizeof(*(object->input));
for (int i=0; i<howManyCharPtrsYouWant; i++)
{
obj->input[i] = malloc(howManyCharsYouWant); // sizeof(char) is guaranteed to be 1, so no need to include it in `malloc`
}
See my previous answer for an explanation of sizeof(*(object->input)) if you're unsure what's happening there.
*(obj->input)=malloc(sizeof(char)+1); only allocates space for 2 chars (sizeof char == 1, +1 == 2 total). This is the smallest possible string you can have in C, one char followed by a NUL terminator. So if you're trying to put more than 2 chars in that buffer, that's an overflow --> UB --> possible segfault. If all you need is one char, better to bypass the malloc and simply use char c;, for example.
This is getting off topic, but the top two reasons you need dynamic memory allocation IMO are:
You won't know how much memory you'll need until runtime
You need "a lot" of memory (on your regular vanilla PC, I'd put this around 4+MB, but of course your mileage may vary depending on your needs and system).
SO has some good questions weighing the benefits of when to malloc or not, you can look them up.
If you know at compile time you'll need a max of 30 strings, only 30 chars long for example, then you can do something like
struct shard
{
sem_t *semaphore_o;
char input[30][30];
// .. etc
};
and
struct shard obj; // you only need one of these, malloc makes little sense IMO
obj.semaphore_o = malloc(..); // this doesn't need to be a pointer either
strcpy(input[0], "hello there"); // fits in 29 chars plus NUL
strcpy(input[5], "I'm Jim"); // same
My preference is always to use automatic (stack) storage when possible, it's simpler because it relieves you of the burden of memory management.
I have a bit of an issue.
I'll explain, I'm trying to create a dynamic memory allocation for a string inside a struct and print it.
The thing is, it doesn't care about the size I dynamically allocate.
For example, I create a string in the size of size 6, but it let's me insert 15 chars and prints them all.
So basically, it doesn't limit me on the string size, why's so?
typedef struct{
int grade;
int id;
int arr[5];
char *str;
}student;
int main(){
puts("How many many letters in char?\n");
scanf("%d", &num);
getchar();
student1.str = (char *)malloc(sizeof(char)*num+1);
gets(buffer);
strcopy(student1.str, buffer);
}
BTW, I tried to keep the code clear as possible for you guys/ladies, just with the main things I need. I know I didn't free the memory or checked if allocation failed etc...
First to say, please see this discussion on why not to cast the return value of malloc() and family in C..
Coming to the main issue here, out of bound memory access causes undefined behavior.
So basically, it doesn't limit me on the string size, why's so?
There is nothing in the C standard itself to prevent you from accessing out of bound memory (i.e, accessing the memory which is not allocated to your process), but any attempt to do so will lead to UB. Don't do that.
That said,
Never use gets(), it suffers from buffer overrun issues, use fgets() instead.
sizeof(char) is defined to be 1 in C. Using that as a multiplier is redundant.
The malloc is giving you the permission to write to the memory but you can try and write without permission. That is what you just did. It may work and it may not, but If you will use malloc properly you should be able to run this code run-time-error-free
When you use C, a major part of the job of programming, is to make sure that any data that hits your allocated memory will actually fit. This is why C programming can be such a pain. It also requires you to free your memory when you don't use it anymore, which you forgot in your example.
I seem to be having some issues with malloc in my code. Here's what's going on.
I've got a struct created with a few values in it. From there, I'd like to make an array of structs. I think I've got the struct right, and some of the pointers, but I'm not sure.
Here's the struct:
typedef struct{
char name[25];
int courseID;
} course;
From there, I try to initiate the new struct and malloc it at the same time by this:
course *courses = malloc(25*sizeof(course));
From here, I'm getting the error:
Invalid conversion from 'void*' to 'course*' [-fpermissive] course
*courses = malloc(25*sizeof(course));
I don't really know what this means... I know I may be completely off course with this whole idea, so any help y'all can give would be great!
You must be using a C++ compiler. You want to compile with a C compiler.
Make sure your file name ends in .c not .cpp or .cc.
You also said you try to initialize (you said initiate but I am translating) the new struct. Malloc will not do that. Malloc allocated memory will contain random values left over from the last user of that memory. The calloc function might work better for what you want since it sets the memory to zero after allocating it.
You are initializing memory with malloc, which returns a void pointer to the allocated memory. You are then assigning this pointer to a course pointer. So there is a pointer mismatch and hence the warning. To bypass it use
course *courses = (course *)malloc(25 * sizeof(course))
I just learned that it's possible to increase the size of the memory you'll allocate to a struct when using the malloc function. For example, you can have a struct like this:
struct test{
char a;
int v[1];
char b;
};
Which clearly has space for only 2 chars and 1 int (pointer to an int in reality, but anyway). But you could call malloc in such a way to make the struct holds 2 chars and as many ints as you wanted (let's say 10):
int main(){
struct test *ptr;
ptr = malloc (sizeof(struct test)+sizeof(int)*9);
ptr->v[9]=50;
printf("%d\n",ptr->v[9]);
return 0;
}
The output here would be "50" printed on the screen, meaning that the array inside the struct was holding up to 10 ints.
My questions for the experienced C programmers out there:
What is happening behind the scenes here? Does the computer allocate 2+4 (2 chars + pointer to int) bytes for the standard "struct test", and then 4*9 more bytes of memory and let the pointer "ptr" put whatever kind of data it wants on those extra bytes?
Does this trick only works when there is an array inside the struct?
If the array is not the last member of the struct, how does the computer manage the memory block allocated?
...Which clearly has space for only 2 chars and 1 int (pointer to an
int in reality, but anyway)...
Already incorrect. Arrays are not pointers. Your struct holds space for 2 chars and 1 int. There's no pointer of any kind there. What you have declared is essentially equivalent to
struct test {
char a;
int v;
char b;
};
There's not much difference between an array of 1 element and an ordinary variable (there's conceptual difference only, i.e. syntactic sugar).
...But you could call malloc in such a way to make it hold 1 char and as
many ints as you wanted (let's say 10)...
Er... If you want it to hold 1 char, why did you declare your struct with 2 chars???
Anyway, in order to implement an array of flexible size as a member of a struct you have to place your array at the very end of the struct.
struct test {
char a;
char b;
int v[1];
};
Then you can allocate memory for your struct with some "extra" memory for the array at the end
struct test *ptr = malloc(offsetof(struct test, v) + sizeof(int) * 10);
(Note how offsetof is used to calculate the proper size).
That way it will work, giving you an array of size 10 and 2 chars in the struct (as declared). It is called "struct hack" and it depends critically on the array being the very last member of the struct.
C99 version of C language introduced dedicated support for "struct hack". In C99 it can be done as
struct test {
char a;
char b;
int v[];
};
...
struct test *ptr = malloc(sizeof(struct test) + sizeof(int) * 10);
What is happening behind the scenes here? Does the computer allocate
2+4 (2 chars + pointer to int) bytes for the standard "struct test",
and then 4*9 more bytes of memory and let the pointer "ptr" put
whatever kind of data it wants on those extra bytes?
malloc allocates as much memory as you ask it to allocate. It is just a single flat block of raw memory. Nothing else happens "behind the scenes". There's no "pointer to int" of any kind in your struct, so any questions that involve "pointer to int" make no sense at all.
Does this trick only works when there is an array inside the struct?
Well, that's the whole point: to access the extra memory as if it belongs to an array declared as the last member of the struct.
If the array is not the last member of the struct, how does the computer manage the memory block allocated?
It doesn't manage anything. If the array is not the last member of the struct, then trying to work with the extra elements of the array will trash the members of the struct that declared after the array. This is pretty useless, which is why the "flexible" array has to be the last member.
No, that does not work. You can't change the immutable size of a struct (which is a compile-time allocation, after all) by using malloc ( ) at run time. But you can allocate a memory block, or change its size, such that it holds more than one struct:
int main(){
struct test *ptr;
ptr = malloc (sizeof(struct test) * 9);
}
That's just about all you can do with malloc ( ) in this context.
In addition to what others have told you (summary: arrays are not pointers, pointers are not arrays, read section 6 of the comp.lang.c FAQ), attempting to access array elements past the last element invokes undefined behavior.
Let's look at an example that doesn't involve dynamic allocation:
struct foo {
int arr1[1];
int arr2[1000];
};
struct foo obj;
The language guarantees that obj.arr1 will be allocated starting at offset 0, and that the offset of obj.arr2 will be sizeof (int) or more (the compiler may insert padding between struct members and after the last member, but not before the first one). So we know that there's enough room in obj for multiple int objects immediately following obj.arr1. That means that if you write obj.arr1[5] = 42, and then later access obj.arr[5], you'll probably get back the value 42 that you stored there (and you'll probably have clobbered obj.arr2[4]).
The C language doesn't require array bounds checking, but it makes the behavior of accessing an array outside its declared bounds undefined. Anything could happen -- including having the code quietly behave just the way you want it to. In fact, C permits array bounds checking; it just doesn't provide a way to handle errors, and most compilers don't implement it.
For an example like this, you're most likely to run into visible problems in the presence of optimization. A compiler (particularly an optimizing compiler) is permitted to assume that your program's behavior is well-defined, and to rearrange the generated code to take advantage of that assumption. If you write
int index = 5;
obj.arr1[index] = 42;
the compiler is permitted to assume that the index operation doesn't go outside the declared bounds of the array. As Henry Spencer wrote, "If you lie to the compiler, it will get its revenge".
Strictly speaking, the struct hack probably involves undefined behavior (which is why C99 added a well-defined version of it), but it's been so widely used that most or all compilers will support it. This is covered in question 2.6 of the comp.lang.c FAQ.
OK, I hope I explain this one correctly.
I have a struct:
typedef struct _MyData
{
char Data[256];
int Index;
} MyData;
Now, I run into a problem. Most of the time MyData.Data is OK with 256, but in some cases I need to expand the amount of chars it can hold to different sizes.
I can't use a pointer.
Is there any way to resize Data at run time? How?
Code is appreciated.
EDIT 1:
While I am very thankful for all the comments, the "maybe try this..." or "do that", or "what you are dong is wrong..." comments are not helping. Code is the help here. Please, if you know the answer post the code.
Please note that:
I cannot use pointers. Please don't try to figure out why, I just can't.
The struct is being injected into another program's memory that's why no pointers can be used.
Sorry for being a bit rough here but I asked the question here because I already tried all the different approaches that thought might work.
Again, I am looking for code. At this point I am not interested in "might work..." or " have you considered this..."
Thank you and my apologies again.
EDIT 2
Why was this set as answered?
You can use a flexible array member
typedef struct _MyData
{
int Index;
char Data[];
} MyData;
So that you can then allocate the right amount of space
MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;
Later, you can free, and allocate another chunk of memory and make a pointer to MyData point to it, at which time you will have more / less elements in the flexible array member (realloc). Note that you will have to save the length somewhere, too.
In Pre-C99 times, there isn't a flexible array member: char Data[] is simply regarded as an array with incomplete type, and the compiler would moan about that. Here i recommend you two possible ways out there
Using a pointer: char *Data and make it point to the allocated memory. This won't be as convenient as using the embedded array, because you will possibly need to have two allocations: One for the struct, and one for the memory pointed to by the pointer. You can also have the struct allocated on the stack instead, if the situation in your program allows this.
Using a char Data[1] instead, but treat it as if it were bigger, so that it overlays the whole allocated object. This is formally undefined behavior, but is a common technique, so it's probably safe to use with your compiler.
The problem here is your statement "I can't use a pointer". You will have to, and it will make everything much easier. Hey, realloc even copies your existing data, what do you want more?
So why do you think you can't use a pointer? Better try to fix that.
You would re-arrange the structure like that
typedef struct _MyData
{
int Index;
char Data[256];
} MyData;
And allocate instances with malloc/realloc like that:
my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );
This is an ugly approach and I would not recommend it (I would use pointers), but is an answer to your question how to do it without a pointer.
A limitation is that it allows for only one variable size member per struct, and has to be at the end.
Let me sum up two important points I see in this thread:
The structure is used to interact between two programs through some IPC mechanism
The destination program cannot be changed
You cannot therefore change that structure in any way, because the destination program is stuck trying to read it as currently defined. I'm afraid you are stuck.
You can try to find ways to get the equivalent behavior, or find some evil hack to force the destination program to read a new structure (e.g., modifying the binary offsets in the executable). That's all pretty application specific so I can't give much better guidance than that.
You might consider writing a third program to act as an interface between the two. It can take the "long" messages and do something with them, and pass the "short" messages onward to the old program. You can inject that in between the IPC mechanisms fairly easily.
You may be able to do this like this, without allocating a pointer for the array:
typedef struct _MyData
{
int Index;
char Data[1];
} MyData;
Later, you allocate like this:
int bcount = 256;
MyData *foo;
foo = (MyData *)malloc(sizeof(*foo) + bcount);
realloc:
int newbcount = 512;
MyData *resized_foo;
resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
It looks like from what you're saying that you definitely have to keep MyData as a static block of data. In which case I think the only option open to you is to somehow (optionally) chain these data structures together in a way that can be re-assembled be the other process.
You'd need and additional member in MyData, eg.
typedef struct _MyData
{
int Sequence;
char Data[256];
int Index;
} MyData;
Where Sequence identifies the descending sequence in which to re-assemble the data (a sequence number of zero would indicate the final data buffer).
The problem is in the way you're putting the question. Don't think about C semantics: instead, think like a hacker. Explain exactly how you are currently getting your data into the other process at the right time, and also how the other program knows where the data begins and ends. Is the other program expecting a null-terminated string? If you declare your struct with a char[300] does the other program crash?
You see, when you say "passing data" to the other program, you might be [a] tricking the other process into copying what you put in front of it, [b] tricking the other program into letting you overwrite its normally 'private' memory, or [c] some other approach. No matter which is the case, if the other program can take your larger data, there is a way to get it to them.
I find KIV's trick quite usable. Though, I would suggest investigating the pointer issue first.
If you look at the malloc implementations
(check this IBM article, Listing 5: Pseudo-code for the main allocator),
When you allocate, the memory manager allocates a control header and
then free space following it based on your requested size.
This is very much like saying,
typedef struct _MyData
{
int size;
char Data[1]; // we are going to break the array-bound up-to size length
} MyData;
Now, your problem is,
How do you pass such a (mis-sized?) structure to this other process?
That brings us the the question,
How does the other process figure out the size of this data?
I would expect a length field as part of the communication.
If you have all that, whats wrong with passing a pointer to the other process?
Will the other process identify the difference between a pointer to a
structure and that to a allocated memory?
You cant reacolate manualy.
You can do some tricks wich i was uning when i was working aon simple data holding sistem. (very simple filesystem).
typedef struct
{
int index ;
char x[250];
} data_ztorage_250_char;
typedef struct
{
int index;
char x[1000];
} data_ztorage_1000_char;
int main(void)
{
char just_raw_data[sizeof(data_ztorage_1000_char)];
data_ztorage_1000_char* big_struct;
data_ztorage_250_char* small_struct;
big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
// notice that upper line is same as writing
// big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);
small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct
//both structs starts at same locations and they share same memory
//addresing data is
small_struct -> index = 250;
}
You don't state what the Index value is for.
As I understand it you are passing data to another program using the structure shown.
Is there a reason why you can't break your data to send into chunks of 256bytes and then set the index value accordingly? e.g.
Data is 512 bytes so you send one struct with the first 256 bytes and index=0, then another with the next 256 bytes in your array and Index=1.
How about a really, really simple solution? Could you do:
typedef struct _MyData
{
char Data[1024];
int Index;
} MyData;
I have a feeling I know your response will be "No, because the other program I don't have control over expects 256 bytes"... And if that is indeed your answer to my answer, then my answer becomes: this is impossible.