The following code causes a SIGSEGV, but only while debugging.
#include <stdio.h>
#include <stdlib.h>
typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;
int main()
{
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
enemies[0]->type=23;
printf("%i",enemies[0]->type);
return 0;
}
You are only creating space for 16 pointers to enemy, but are not creating the actual enemy objects that you're attempting to use.
Here is an example where I create an enemy object to the first pointer in the array.
#include <iostream>
typedef struct enemy_desc
{
int type;
int x;
int y;
}enemy;
using namespace std;
int main(int argc, char **argv)
{
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
memset(enemies, 0, sizeof(enemy*)*16);
enemies[0] = (enemy *) malloc(sizeof(enemy));
memset(enemies[0], 0, sizeof(enemy));
enemies[0]->type=23;
printf("type: %i x: %i y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);
enemies[0]->x = 10;
enemies[0]->y = 25;
enemies[0]->type= 7;
printf("type: %i x: %i y: %i\n\n",enemies[0]->type, enemies[0]->x, enemies[0]->y);
free(enemies[0]);
free(enemies);
return 0;
}
You have allocated memory for 16 enemy * pointers, but you have not allocated room for the 16 enemy structs themselves. There are two ways to fix this. One is to add a loop that allocates each of the 16 enemy structs one by one:
int main()
{
enemy **enemies;
int i;
enemies = (enemy **) malloc(sizeof(enemy *) * 16);
for (i = 0; i < 16; ++i) {
enemies[i] = (enemy *) malloc(sizeof(enemy));
}
enemies[0]->type = 23;
printf("%i",enemies[0]->type);
return 0;
}
The other is to remove one level of indirection. If you declare enemy *enemies then you can allocate the 16 structs at once and forgo a loop. If there's no need for the double indirection this would be my preferred solution:
int main()
{
enemy *enemies;
enemies = (enemy *) malloc(sizeof(enemy) * 16);
enemies[0].type=23;
printf("%i",enemies[0].type);
return 0;
}
Notice that the -> operator switches to ..
You need to create the struct that the pointers point to. The reason why it only gives a SEGV while debugging will be that there's some initialisation done during debugging to cause this sort of thing to segfault; whatever random data's in enemies[0] when you're not debugging is getting dereferenced and is just happening not to cause a segfault.
Your code probably wants to read like this:
int main()
{
enemy *enemies;
enemies=(enemy *)malloc(sizeof(enemy)*16);
enemies[0].type=23;
printf("%i",enemies[0].type);
return 0;
}
Well it should crash right away... because you initialize the array of (array of pointers). And then you DEREFERENCE the first item (enemies[0]) which should give you any random pointer. You try to access that random memory area to write in the value 23.
It should be along the lines of this:
enemies = (enemy **)malloc(sizeof(enemy *) * 16);
for (int i = 0; i < 16; i++) {
enemies[i] = (enemy *)malloc(sizof(enemy));
}
... before you access it.
Looks like you want to allocate an array of pointer to struct, but you're trying to access the struct without allocating space for them. You should do:
enemy **enemies;
enemies=(enemy **)malloc(sizeof(enemy *)*16);
for(i=0;i<16;i++) // allocate space for the structs
enemies[i] = (enemy *)malloc(sizeof(enemy))
enemies[0]->type=23; // now access type field of the first struct obj in array.
On my system (x86, Debian GNU/Linux), the code always segfaults.
Crash backtrace:
signal SIGSEGV, Segmentation fault.
0x08048413 in main () at en.c:16
16 enemies[0]->type=23;
(gdb)
The assignment cited (enemies[0]->type=23;) is the problem. You only allocate memory for the array enemies, which is an array of pointers. You then access the structure that enemies[0] is supposed to point to, but you have not allocated memory for the structure, and enemies[0] is an uninitialized pointer, hence the segfault.
In cases like this, a debugger is your friend :-).
Related
My issue is with nums3 array and why the last for-loop actually prints expected results. The nums3 array as I understand it contains an array of pointers to the struct but these pointers have not yet been initialized to any specific instance of a struct. But in this for-loop I can assign values and see the expected results display.
Also, I've read that with the pointer returned by malloc I can use the [index] after the pointer and iterate over the allocated memory. I assume this feature is using the fact it has a type multiplied by some value and it does the division automatically to know how this block of memory is split up and therefore how far to advance to the next index. But I'm still confused as to why I'm getting expected results on that last for-loop when I haven't initialized or pointed those pointers to anything specific.
I know that if I were to add ** and change the to -> then I could operate on those pointers directly, but with the code now I'm able to use the . operator to access structure members. So, without the ** in the nums3 malloc line, what exactly does the pointer returned from malloc return?
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_MAX 5
int main(void)
{
struct number {
int num1;
int num2;
int num3;
};
struct number n;
n.num1 = 5;
printf("n.num1: %d\n", n.num1);
n.num2 = 6;
printf("n.num2: %d\n", n.num2);
n.num3 = 7;
printf("n.num3: %d\n", n.num3);
struct number nums1[5];
struct number* nums2 = malloc(sizeof(struct number) * ARRAY_MAX);
struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
int x;
for(x = 0; x <= 5; x++) {
nums1[x].num1 = x;
nums1[x].num2 = x;
nums1[x].num3 = x;
}
int y;
for(y = 0; y <= ARRAY_MAX; y++) {
nums2[y].num1 = x;
nums2[y].num2 = x;
nums2[y].num3 = x;
}
for(y=0; y<=ARRAY_MAX; y++) {
nums3[y].num1 = y;
nums3[y].num2 = y;
nums3[y].num3 = y;
printf("%d ", nums3[y].num1);
printf("%d ", nums3[y].num2);
printf("%d \n", nums3[y].num3);
}
Here is a simpler test case of my question:
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
int main(void)
{
struct number {
int num1;
};
struct number* n = malloc(sizeof(struct number*) * MAX);
int i;
for(i=0; i<MAX; i++) {
n[i].num1 = i;
printf("%d\n", n[i]);
}
free(n);
}
Result of running this code:
jason smith#jasonS-pc ~/src/c
$ ./a.exe
0
1
2
3
4
jason smith#jasonS-pc ~/src/c
$
Questions:
How does n[i] work with n being the pointer returned from malloc? How does C know what to do with n[i]? How does C know how to get to n[i+1]? Does it look at what sizeof() is being called on and divide by however many times it is multiplied and use that result to know where the next cell starts?
Why does n[i].num1 = i; even compile? If all I have done is specify a block of memory containing size for x number of pointers to the struct (pointers which would be smaller than the size of the struct itself) and certainly have not initialized anything to point to an actual instance of this struct. Why isn't this a syntax or some other compiler generated error? What exists at cell n[i] that .num1 is working on? Doesn't n[i] right now just contain a pointer without a valid address since it's not yet initialized? How do we go from that to n[i].num1 = i? Is it valid syntax to do "some memory address".num1 = "some value"?
I understand this is not the correct way to do this, and you all have provided great information, but I'm still puzzled as to why this code even compiles. It just doesn't make sense to me.
In general, if you access memory incorrectly you cannot expect anything. You can't expect to get the right answer, and you can't expect to get the wrong answer. You can't expect your program to crash and you can't expect it to run. Again, it can do anything.
The error here is that you allocated an array of pointers but then chose the wrong type to hold the result.
// This is wrong!
struct number* nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
You want this:
struct number **nums3 = malloc(sizeof(struct number*) * ARRAY_MAX);
// ^^
Or really, this way is better:
struct number **nums3 = malloc(sizeof(*nums3) * ARRAY_MAX);
Then you have an array of (uninitialized) pointers to play with. For example,
for (int i = 0; i < ARRAY_MAX; i++) {
nums3[i] = malloc(sizeof(*nums3[i]));
nums3[i]->num1 = i;
nums3[i]->num2 = i;
nums3[i]->num3 = i;
}
or...
for (int i = 0; i < ARRAY_MAX; i++) {
nums3[i] = &nums2[i];
}
Whatever you want.
(We're pretending here that malloc() doesn't return NULL which is not guaranteed.)
You are correct by saying you are not allocating enough space as sizeof(struct number) = 12 while sizeof(struct number*) = 8
Malloc finds a free memory according to the size you asked and (if successful) returns you a pointer to the first address (this is virtual memory). If you exceed the size created you enter the realm of unexpected behavior. Meaning you either will be able to write and read data from the memory or you won't and even if you manage to do that, you can accidentally overwrite areas in memory storing other data.
In this case, although printing passed with no special behavior, when you try to free(nums3) you will get an error.
Also, if you will reverse the order of nums2 and nums3 declaration and print nums2 after nums3 loop, you will probably be able to see this corruption of data.
Hope this is helpful
I am using an array of structs and then set up the elements like the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct _point {
char s;
unsigned int x;
unsigned int y;
} point;
point* vehicle;
int main(int argc, char *argv[]) {
/* 26 Vehicles */
vehicle = malloc(26*sizeof(point*));
for (int i = 0; i < 26; i++) {
vehicle[i].s = ' ';
}
/* Print already existing vehicles */
for (int i = 0; i < 26; i++) {
if (vehicle[i].s != ' ') {
printf("%c: x=%d y=%d\n", vehicle[i].s, vehicle[i].x, vehicle[i].y);
}
}
return 0;
}
NOTE: this is not the actual code (which is too big to post) but the set up of the array and structs is the same.
As you can see, I set every vehicle[i].s to the space character, but the loop prints the following (not it this example code but in my actual code):
: x=32215344 y=0
P: x=0 y=33
: x=2105376 y=0
Question: how can it be that after the first loop, some elements are modified in the "background" without assigning them in the code? Or can some other malloc operations overwrite/reallocate the memory?
The problem, as I see it is in
vehicle = malloc(26*sizeof(point*));
you're allocating memory for the pointer-to-the-data-type type, whereas you should be allocating for the data type itself.
To elaborate, you want to allocate memory for 26 elements of type point (i.e., struct _point), not 26 point *.
Change
vehicle = malloc(26*sizeof(point));
or, for better,
vehicle = malloc(26*sizeof * vehicle);
Otherwise, you're running short of allocated memory when you try to dererference the pointer to access ns of instances. So, you end up accessing out-of-bound memory which causes undefined behavior.
That said, just an advice, if you know the size to be allocated beforehand, (26, for example), don't use dynamic memory, there's no need for it. Use an array.
I am having a problem in a program I am writing. This small program is a short version just to show the problem.
For this example, I am defining a structure called point which has an X and Y. I want the function to calculate the number of points, In this example I am assuming always 5, but this is not constant in my real program.
#include <stdio.h>
typedef struct point {
int x;
int y;
}point;
// suppose this is dynamic. it return a value according to some parameter;
int howManyPoints() {
// for this demo assume 5.
return 5;
}
int createAnArrayOfPoints(point** outArray,int* totalPoints) {
// how many points?
int neededPoints = howManyPoints();
// create an array of pointers
*outArray =malloc(neededPoints * sizeof(point*));
// malloc memory of a point size for each pointer
for (int i=0;i<neededPoints;i++) outArray[i] = malloc(sizeof(point));
// fill the points with some data for testing
for (int k=0;k<neededPoints;k++) {
outArray[k]->x = k*10;
outArray[k]->y = k*5;
}
// tell the caller the size of the array
*totalPoints = neededPoints;
return 1;
}
int main(int argc, const char * argv[]) {
printf("Program Started\n");
point* arrayOfPoints;
int totalPoints;
createAnArrayOfPoints(&arrayOfPoints,&totalPoints);
for (int j=0;j<totalPoints;j++) {
printf("point #%d is at %d,%d\n",j,arrayOfPoints[j].x,arrayOfPoints[j].y);
}
printf("Program Ended\n");
return 0;
}
My console output looks like this:
Program Started
point #0 is at 0,0
point #1 is at 0,0
point #2 is at 10,5
point #3 is at 0,0
point #4 is at 20,10
Program Ended
What am I doing wrong? I am expecting all 5 points to have values in them..
Thanks.
You have a mismatch in your representation for the array:
In your main you are expecting an array of points (point* arrayOfPoints;) that is one consecutive piece of memory. However, the way you allocate it in createAnArrayOfPoints is different:
In that function you let arrayOfPoints point at a piece of memory only carrying pointers to point and initialize it with pointers to memory of the size of point you allocated. This is one indirection too much and also yields accesses outside of the allocated memory when printing.
Instead you should have done something like this:
// Allocate enough memory to store an array of points of the expected size.
// To keep the code more readable, the resulting pointer is stored in a
// intermediate variable.
points *theArray = malloc(neededPoints * sizeof(point));
if (theArray == NULL) {
// do some error handling here as you apparently ran out of memory...
}
// fill the points with some data for testing
for (int k=0;k<neededPoints;k++) {
theArray[k].x = k*10;
theArray[k].y = k*5;
}
// Now save the pointer to the output-variable.
*outArray = theArray;
Let me also add a word of warning: You always should check whether the malloc was successful or not before using the return value. It might be that you ran out of memory and therefor won't get what you requested.
You don't need to use 2 mallocs. Try the code below. Your approach tries to actually create a matrix of points and initializes the first element of each line.
When you print you actually print the first line that hasn't been initialized fully.
int createAnArrayOfPoints(point** outArray,int* totalPoints) {
// how many points?
int neededPoints = howManyPoints();
// create an array of pointers
*outArray =(point*)malloc(neededPoints * sizeof(point));
// fill the points with some data for testing
for (int k=0;k<neededPoints;k++) {
(*outArray)[k].x = k*10;
(*outArray)[k].y = k*5;
}
// tell the caller the size of the array
*totalPoints = neededPoints;
return 1;
}
You should allocate an array of point structures, not an array of pointers to point structures. Furthermore, you are mixing indirection levels.
Use a local variable point *array; to hold the pointer to the allocated array and access it as array[i].x = k*10;... and store this pointer as *outArray = array
I'm creating a pointer to a pointer to a structure to create a dynamic array with malloc in C, but I get a segmentation fault calling the struct array. Here is a quick rundown of my code:
#include <stdio.h>
typedef struct {
int test1;
int test2;
}testStruct;
int main() {
testStruct **neato;
neato = (testStruct **) malloc( sizeof(testStruct *) * 5);
// Array of 5 for convience
// any neato[x]->testy call results in segmentation fault.
scanf("%d", &neato[0]->test1); // Segmentation fault
return 0;
}
I tried other calls like (*neato)[0].test1 and all result in segmentation fault. This is obviously not the proper way to do this or my GNU compiler is seriously outdated.
You've allocated enough memory for 5 pointers. You have not however initialized the pointers, so they are garbage. Allocate the pointers and then proceed to initialize each pointer.
int elems = 5;
neato = malloc(sizeof(testStruct *) * elems);
for( i = 0; i < elems; ++i ) {
neato[i] = malloc(sizeof(testStruct));
}
On a side note, I don't see a need for an array of pointers here. Why not simply allocate enough space for 5 testStructs (i.e., neato becomes a testStruct*) and pass the address of that pointer to the function that initializes it?
you aren't mallocing space for all the structures themselves you have to add
for(int i = 0; i < 5; i++) {
neato[i] = malloc(sizeof(testStruct));
}
After you malloc neato. Also you should check your return value from malloc for NULL to make sure malloc passed.
You allocated array of pointers, but did not assign valid address to these pointers.
If you only want to create dynamic array, use just pointer to the struct:
testStruct *neato;
neato = malloc( sizeof(testStruct) * 5);
scanf("%d", &neato[0].test1);
I am using a struct and I want to initialize a maximum of 10 ports. However, when the program is running it could be a lot less, we don't know until run-time. However, this will be the max. I have never done struct like this before, as I normally dynamically allocate using calloc and delcare like this *ports as the value type.
However, I can't understand this
*ports[MAX_PORTS]. Am I creating 10 pointers that point to port objects?
And
*ports = (struct port_t*) calloc(2, sizeof(*ports));
Looks like I am allocating a single pointer that points to 2 port objects allocated on the free store?
I can't understand why I am using a dot operator with a arrow operator?
ports[0]->port_id = 20;
printf("port_id: %d\n", ports[0]->port_id);
#include <stdio.h>
#include <stdlib.h>
#define MAX_PORTS 10
struct port_t
{
int port_id;
char name;
} *ports[MAX_PORTS];
int main(void)
{
*ports = (struct port_t*) calloc(2, sizeof(*ports));
ports[0]->port_id = 20;
printf("port_id: %d\n", ports[0]->port_id);
return 0;
}
normally, what I have done in the passed is this:
struct port_t
{
int port_id;
char name;
} *ports;
ports = (struct port_t*) calloc(2, sizeof(*ports));
And then assign with either of the following below. However, the previous programmer has declared everything like I have displayed at the top so I can't change anything.
ports[0].port_id = 10;
ports->port_id = 10;
Many thanks for any suggestions,
Your first code block has
struct port_t
{
int port_id;
char name;
} *ports[MAX_PORTS];
which is an array of pointers. This means later when you use
ports[0]->port_id
you are dereferencing the first pointer in the array. There is also some ugliness surrounding the size of what you are actually calloc'ing. You're actually replacing your array of 10 with an array of 2. What you've got there is generally ugly and error prone.
I believe your intentions are more along the lines of:
struct port_t
{
int port_id;
char name;
} *ports;
int main(void)
{
*ports = (struct port_t*) calloc(2, sizeof(*ports));
ports[0].port_id = 20;
printf("port_id: %d\n", ports[0].port_id);
return 0;
}
Since you are using C99, you could avoid calloc()/malloc(), if you really want to by using C99's variable array declaration.
port_t array_on_mains_stack[some_runtime_port_count];
ports = array_on_mains_stack;
The trick there is that since it is on the stack, it is only valid from that function and any function called by it. Once you return from that function, it is of course freed.
*ports[MAX_PORTS]. Am I creating 10 pointers that point to port objects?
Yes, you're making an array of ten pointers
*ports = (struct port_t*) calloc(2, sizeof(*ports));
...but this line is nonsense. It's the same as this:
ports[0] = (struct port_t*) calloc(2, sizeof(port_t));
ie. You're setting the first pointer to point to enough memory for two ports.
For such a small thing it would make much more sense to make ten ports but not use them all:
#define MAX_PORTS 10
struct port_t
{
int port_id;
char name;
} ports[MAX_PORTS];
/* number of ports in use */
int numPorts = 0;
int main(void)
{
numPorts = 3;
for (int i=0; i<numPorts; i++) {
ports[i].port_id = i;
printf("port_id %d: %d\n", i, ports[i].port_id);
}
return 0;
}
ports is and array of pointers to port_t objects, so by doing ports[0] you get a pointer, not an object, and you need to access it with ->
Grab a good resource on pointers in C and read it from cover to cover. There are also tutorials on reading C declarations. You won't be able to understand this topic by getting answers to random questions.
Here's a link worth reading.