Unable to access struct data using arrow notation when pointer - c

I have created an array of structs and I am getting a BAD_ACCESS error. When I switch everything to dot notation it works fine, why is this?
Struct
typedef struct data{
int num;
}data;
Main
int main(void){
// This works
data data[4];
data[0].num = 10;
printf("Number is = %d\n", data[0].num);
// This does not work
data *data[4];
data[0]->num = 10;
printf("Number is = %d\n", data[0]->num);

// This does not work
data *data[4];
data[0]->num = 10;
printf("Number is = %d\n", data[0]->num);
Since data is an array of four pointers, data[0] is the first of those four pointers. But what does it point to? Since you haven't done something like data[0] = malloc(sizeof(struct data));, it points to nothing in particular -- uninitialized garbage. It's not surprising that trying to write to what the pointer points to causes a bad access error.
Before you dereference a pointer, you need to make the pointer actually point to something.

Related

Able to Print Expected Results From Uninitialized Array of Pointers to Structures - Confused

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

Moving array of smaller structs into array of larger structs in C

Today I was working on a problem of moving an array of smaller structs directly into an array of larger structs (arrayNew) (essentially upgrading the smaller structs to store more information). The smaller structs needed to be read from a HDD in one single read operation into the array of new 'upgraded' larger structs, a function would be called to do the 'upgrading'. Also all the new fields in the structs that were read from the hard drive would be set to '0'.
Other more simple solutions that I tried were:
Creating a local array of the old structures (arrayOld), loading the structures from the HDD into it then simply looping through the empty array of the new structures (arrayNew) and manually moving each structs contents from arrayOld into arrayNew. (e.g. arrayNew[i].x = arrayOld[i].x; )
The problem with this is that in my case the arrays I was working with were very large and too large for the stack ( about 1mb for each array) causing a segmentation fault the instant the upgrading function was called.
Another viable solution was to create a dynamic array of the old structures (arrayDy) and load the old structures into arrayDy and then again manually moving each structs contents from arrayDy into arrayNew. (e.g. arrayNew[i].y = arrayDy[i].y; ) This addressed the issue of running out of stack memory.
After implementing the second solution. I decided to experiment and develop a solution that uses no dynamically allocated memory and loads the array of old structures from the HHD directly into the larger array of larger structs arrayNew in one read operation and manipulate the contents of arrayNew in memory to pad out the missing values that are there due to the array being bigger.
I will post my solution below in a scaled down version of what I implemented, using the following structs for my example:
typedef struct INNER_STRUCT_ {
int i_item1;
int i_item2;
char i_item3;
} INNER_STRUCT;
typedef struct SMALL_STRUCT_ {
int item1;
char item2;
INNER_STRUCT item3;
} SMALL_STRUCT;
typedef struct BIG_STRUCT_ {
int item1;
char item2;
INNER_STRUCT item3;
INNER_STRUCT item4;
} BIG_STRUCT;
Yes, this is possible - you can use union for that. C99 standard makes a special guarantee that can be used to implement your requirement:
6.5.2.3-5: One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the complete type of the union is visible.
Your structA_ and structB_ do share a common initial sequence, so creating a union and accessing the structs through it would do the trick:
union {
structA a;
structB b;
} u;
memset(&u.b, 0, sizeof(structB)); // Zero out the bigger structB
loadFromHdd(&u.a); // Load structA part into the union
// At this point, u.b is valid, with its structA portion filled in
// and structB part zeroed out.
Note that you cannot do it to an array (unless, of course, you make an array of unions). Each structA needs to be loaded individually into the union, from which it could then be read as structB.
The method I propose and used as a solution basically loads the smaller structs for the HDD ( a file in this case) into the array of new larger structs and then rearranges the block of memory so that each field can be accessed properly. The code to illustrate this is below, and is an mcve.
#include <stdio.h>
#include <string.h>
typedef struct INNER_STRUCT_ {
int i_item1;
int i_item2;
char i_item3;
} INNER_STRUCT;
typedef struct SMALL_STRUCT_ {
int item1;
char item2;
INNER_STRUCT item3;
} SMALL_STRUCT;
typedef struct BIG_STRUCT_ {
int item1;
char item2;
INNER_STRUCT item3;
INNER_STRUCT item4;
/*
Note that the big struct is exactly the same as the small
struct with one extra field - Key to this method working
is the fact that the extension to the struct is appended
at the end, in an array of the structs will be placed one
after the other in memory with no gaps*/
} BIG_STRUCT;
void printSmallStruct (SMALL_STRUCT *inStruct, int count) {
// Print everything inside given small struct
printf("\n\n Small struct %d, item1: %d \n",count,inStruct->item1);
printf(" Small struct %d, item2: %c \n",count,inStruct->item2);
printf(" Small struct %d, item3.i_item1: %d \n",count,inStruct->item3.i_item1);
printf(" Small struct %d, item3.i_item2: %d \n",count,inStruct->item3.i_item2);
printf(" Small struct %d, item3.i_item3: %c \n",count,inStruct->item3.i_item3);
}
void printBigStruct (BIG_STRUCT *inStruct, int count) {
// Print everything inside given big struct
printf("\n\n Big struct %d, item1: %d \n",count,inStruct->item1);
printf(" Big struct %d, item2: %c \n",count,inStruct->item2);
printf(" Big struct %d, item3.i_item1: %d \n",count,inStruct->item3.i_item1);
printf(" Big struct %d, item3.i_item2: %d \n",count,inStruct->item3.i_item2);
printf(" Big struct %d, item3.i_item3: %c \n",count,inStruct->item3.i_item3);
printf(" Big struct %d, item4.i_item1: %d \n",count,inStruct->item4.i_item1);
printf(" Big struct %d, item4.i_item1: %d \n",count,inStruct->item4.i_item2);
printf(" Big struct %d, item4.i_item1: %c \n",count,inStruct->item4.i_item3);
}
int main() {
SMALL_STRUCT smallStructArray[5]; // The array of small structs that we will write to a file then read
BIG_STRUCT loadedBigStructArray[5]; // The large array of structs that we will read the data from the file into
int i; // Counter that we will use
FILE *pfile; // pointer to our file stream
void *secondary_ptr; // void pointer that we will use to 'chop' memory into the size we want
/* Fill the array of structs (smallStructArray) */
for (i = 0; i < 5; i++) {
/* We fill each field with different data do we can ID that the right data is in the right fields */
smallStructArray[i].item1 = 111;
smallStructArray[i].item2 = 'S';
INNER_STRUCT* temp = &smallStructArray[i].item3;
temp->i_item1 = 777;
temp->i_item2 = 999;
temp->i_item3 = 'I';
}
/* Write the contents of smallStructArray to binary file then display it */
pfile = fopen("test.dat","wb");
if (pfile!=NULL){
for (i = 0; i < 5; i++) {
fwrite(&smallStructArray[i],sizeof(SMALL_STRUCT),1,pfile);
}
fclose(pfile);
}
else{
printf("Unable to open file!");
return 1;
}
for (i = 0; i < 5; i++) {
printSmallStruct(&smallStructArray[i],i);
}
/* Clear array of big structs using memset */
memset(&loadedBigStructArray[0],0,sizeof(loadedBigStructArray));
/* Here we read from the smallStructArray that was aved to file into the loadedBigStructArray */
pfile = fopen("test.dat","rb");
if (pfile !=NULL){
/*
He we pass fread the following: size_t fread(void *args1, size_t args2, size_t args3, FILE *args4)
args1 - a pointer to the beginning of a block of memory, in our case the beginning of the
array loadedBigStructArray.
args2 - the size of the ammout of bytes we wish to read, in our case the size of a SMALL_STRUCT,
the size one of the elments in the array saved to the file.
args3 - the ammount of elements to read, in our case five (which is the number of elements the
array saved to the file has.
args4 - a pointer to a FILE that specifies our input stream.
Essentially what fread will do here is read a block of bytes the size of the array we saved to
the file (smallStructArray) into the array in memory loadedBigStructArray from the
beggining of loadedBigStructArray. Fig 1 illustrates what this will look like in memory.
*/
fread(&loadedBigStructArray,sizeof(SMALL_STRUCT),5,pfile);
fclose(pfile);
}
else{
printf("Unable to open file!");
return 1;
}
/*
Due to the way the array on the file has been read into the array in memory, if we try
to access the data in loadedBigStructArray only the first 5 values will be valid, due to
the memory not being in the order we want. We need to re-arrange the data in loadedBigStructArray
*/
/*
Here we use a void pointer to point to the beggining of the loadedBigStructArray.
we will use this pointer to 'chop' the data loadedBigStructArray into SMALL_STRUCT
sized 'chunks' we can read from.
Due to the way pointers and arrays work in C we can cast the void pointer to any type we want
and get a chunk of memory that size begginnig from the pointer and its off set.
E.g. : int temp = ((int *)void_ptr)[i];
This example above will give us an integer 'temp' that was taken from memory beggining from position
void_ptr in memory and its offset i. ((int *)void_ptr) casts the pointer to type int and [i] dereferances
the pointer to location i.
*/
secondary_ptr = &loadedBigStructArray;
/*
Not we are going through the array backwards so that we can rearange the data with out overwriting
data in a location that has data which we havent moved yet. As the bottom end of the loadedBigStructArray
is essentially empty we can shift data down that way.
*/
for (i = 5; i > -1; i=i-1) {
SMALL_STRUCT temp = ((SMALL_STRUCT *)secondary_ptr)[i]; // dereference pointer to SMALL_STRUCT [i] inside loadedBigStructArray call it 'temp'
/*
Now that we have dereferenced a pointer a given SMALL_STRUCT inside loadedBigStructArray called 'temp'
we can use temp to move the data inside temp to its corresponding position in loadedBigStructArray
which rearragnes the data.
*/
loadedBigStructArray[i].item1 = temp.item1;
loadedBigStructArray[i].item2 = temp.item2;
loadedBigStructArray[i].item3.i_item1 = temp.item3.i_item1;
loadedBigStructArray[i].item3.i_item2 = temp.item3.i_item2;
loadedBigStructArray[i].item3.i_item3 = temp.item3.i_item3;
/* We then fill the new field to be blank */
loadedBigStructArray[i].item4.i_item1 = 0;
loadedBigStructArray[i].item4.i_item2 = 0;
loadedBigStructArray[i].item4.i_item3 = '0';
}
/* Print our new structures */
for (i = 0; i < 5; i++) {
printBigStruct(&loadedBigStructArray[i],i);
}
return 0;
}
Visualization of technique:
When fread does the single read operation of the array saved on disk into the array in memory due to it being smaller it will take up the first potion of the array in memory but the 'bottom' section could be anything, if we try to access the data in the new array with the current handles we have on the data we will either get inaccurate information or a bad piece of memory. We have to rearrange this data before we can use any of our handles on the structs in the array.

Structure program compiles without error, but no result in console window?

Hi friends following practice program getting compiled with zero errors but output is not showing in console window...i think there is something which i am missing ...please guide me...thanks!
struct card{
char *face;
char *suit;
}aCard,deck[52], *cardPtr;
int main()
{
struct card aCard; //define one struct card Variable
struct card *cardPtr; //define a pointer to structure card
cardPtr = &aCard;
printf("%s\n %s\n",cardPtr->face, cardPtr->suit);
system("PAUSE");
return 0;
}
You haven't assigned anything to aCard. Assign values to aCard and then assign it to cardPtr.
aCard.face="Hello";
aCard.suit="world";
cardPtr = &aCard;
Now you can see the values getting printed.
cardPtr->face and cardPtr->suit are uninitialized. Hence, undefined behaviour. Allocate memory, and assign values before printing.
EDIT
cardPtr->face = malloc(n * sizeof(char));
where n is the number of characters that the memory block can hold. You will still have to put something in this char array before printing it.

Run through a structure and print all the values?

I have a pointer to a structure and I'd like to fetch all of its members by trial and error. I'm trying to run through the structure by incrementing the pointer by one and derefencing it. It should return a correct value from the structure (every i*sizeof(int) time) but it doesn't.
What am I doing wrong?
fn (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
{
/*
assume that all struct members are int types
typedef struct
{
mach_msg_bits_t msgh_bits;
mach_msg_size_t msgh_size;
mach_port_t msgh_remote_port;
mach_port_t msgh_local_port;
mach_msg_size_t msgh_reserved;
mach_msg_id_t msgh_id;
} mach_msg_header_t;
size of the struct is 24.
*/
printf("ID: %d \n",InHeadP->msgh_id); //prints 'ID: 1337'
printf("Ptr: %p\n",InHeadP);
for (int i = 0; i <= 24; i++)
{
int deref = *((int*)(InHeadP+i));
printf("InHeadP[%d]=%d\n",i,deref);
//no sign of 1337 anywhere
}
}
P.S. I know that I shouldn't be doing that, but this is only for testing purposes.
Because InHeadP is a mach_msg_header_t*, adding an integer to it will actually add that integer times sizeof(mach_msg_header_t), as though you were indexing an array of mach_msg_header_ts (and is actually how array indexing works). You need to cast InHeadP to an int* before performing arithmetic on it, and even then, as the struct has six fields, i should only go up to 6, not 24.
A preferred method to iterate through a structure is to create a function that returns the value or address of the field given an index. Note that if the order of the members in the struct changes, this function must change too:
int * Index_Of(unsigned int index, mach_msg_header_t * p_struct)
{
switch (index)
{
case 0: return (int *) &(p_struct->msgh_bits);
case 1: return (int *) &(p_struct->msgh_size);
case 2: return (int *) &(p_struct->msgh_remote_port);
case 3: return (int *) &(p_struct->msgh_local_port);
case 4: return (int *) &(p_struct->msgh_reserved);
case 5: return (int *) &(p_struct->msgh_id);
}
return 0;
}
Just remember that treating the structure as contiguous fields (members) is not advisable since the compiler is allowed to add padding between structure members. Thus any method to access the fields except by name, is dangerous and will lead to very difficult bugs.
BTW, treating each field as an int is also dangerous. If any of the types is changed to something else, like a double, your code will break. Compiler will not catch the error because casting tells the compiler YOU know what you are doing.
You could "turn the picture around" and implement a Visitor pattern:
struct Visitor_Void
{
void (*fn_msgh_bits)(mach_msg_bits_t);
void (*fn_msgh_size)(mach_msg_size_t);
void (*fn_msgh_remote_port)(mach_port_t);
void (*fn_msgh_local_port)(mach_port_t);
void (*fn_msgh_reserved)(mach_msg_size_t);
void (*fn_msgh_id)(mach_msg_id_t);
};
void Visit_Members(mach_msg_header_t * p_header,
struct Visitor_Void * p_visitor)
{
(p_visitor->fn_msgh_bits)(p_header->msgh_bits);
(p_visitor->fn_msgh_size)(p_header->msgh_size);
(p_visitor->fn_msgh_remote_port)(p_header->msgh_remote_port);
(p_visitor->fn_msgh_local_port)(p_header->msgh_local_port);
(p_visitor->fn_msgh_reserved)(p_header->msgh_reserved);
(p_visitor->fn_msgh_id)(p_header->msgh_id);
return;
}
No, you shouldn't be doing this!
What is particularly wrong here
for (int i = 0; i <= 24; i++)
{
int deref = *((int*)(InHeadP+i));
printf("InHeadP[%d]=%d\n",i,deref);
}
is that you print the first int of 24 different structs.
When you call (int*)(InHeadP+i) you are doing pointer arithmetic on mach_msg_header_t which is size 24. So your first iteration is at the beginning of the struct, and your second iteration is right after your struct. You are accessing some other memory.
Try (((int*)InHeadP)+i).
Wait a second, this is wrong:
int deref = *((int*)(InHeadP+i));
You want
int deref == *((int*)InHeadP+i)
You skipping 24 bytes each time through the loop, rather than 4.

struct c dynamically allocate memory

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.

Resources