I've been trying to have all my pointers that I use malloc to initialize to be inside an array of pointers (or a pointer of pointers, perhaps), so that I can then just go through that array and free each pointer with something like free(ptr_array[i]); and not have to free each one individually.
I believe that this is possible, but I am having some trouble with my code, as the function that is supposed to free everything (and I would rather keep it all in a separate function, if possible) is apparently unable to properly edit the "sub-pointers", and seemingly they're being copied unlike the "main pointer".
Here's the code, which has me stumped:
#include <stdlib.h>
#include <stdio.h>
void free_test(int** arg){
printf("\tReceived arg addr: %p\n",arg);
printf("\tFreeing arg[0] = %p\n",arg[0]);
//And, just to MAKE SURE that arg[0] is ver, we do this:
printf("\tIn-function ver[0] = %d\n",arg[0][0]);
arg[0][0] = 2;
printf("\tIn-function ver[0] = %d\n",arg[0][0]);
free(arg[0]); //This one doesn't work...
free(arg); //This one works though.
}
int main(){
int** var;
int* ver;
int i;
printf("ver addr 1: %p\n", ver);
ver = malloc( sizeof(int) * 3 );
printf("ver addr 2: %p\n", ver);
for(i=0;i<3;i++){
ver[i] = 5*i;
}
for(i=0;i<3;i++){
printf("ver[%d]: %d\t(# %p)\n",i,ver[i],&(ver[i]));
}
printf("var addr 1: %p\n", var);
var = malloc( sizeof(int *) );
printf("var addr 2: %p\n", var);
var[0] = ver;
printf("var[0] addr = %p\n", var[0]);
free_test(var);
printf("ver[0] new value: %d\n", ver[0]);
//free(var); (free(arg) works in the function, so this one throws an error.)
printf("So far so good, now break.\n");
free(ver);
printf("Didn't break. :(\n");
return 0;
}
And this is the output it currently gives me:
ver addr 1: 0x8048679
ver addr 2: 0x8b0f008
ver[0]: 0 (# 0x8b0f008)
ver[1]: 5 (# 0x8b0f00c)
ver[2]: 10 (# 0x8b0f010)
var addr 1: 0xad7ff4
var addr 2: 0x8b0f018
var[0] addr = 0x8b0f008
Received arg addr: 0x8b0f018
Freeing arg[0] = 0x8b0f008
In-function ver[0] = 0
In-function ver[0] = 2
ver[0] new value: 0
So far so good, now break.
Didn't break. :(
I'm not too great with C, and thus any help would be appreciated. Specially since the value of ver[0] is altered inside the function, but not outside, and I'm guessing that will have to do with why free(...) doesn't work too.
Thanks in advance.
Well my knowledge of C is fading, but IIRC subsequent memory freeing causes undefined behaviour. Thus you are not guaranteed to recive any errors. If I understand it right the behaviour will be varying heavily depending on a particular OS, compiler and stdlib implementation (and even a particular program run).
P.S. My VS2012 VC++ compiler definetly breaks on free(ver);. The output is:
ver addr 1: CCCCCCCC
ver addr 2: 00B8AFF0
ver[0]: 0 (# 00B8AFF0)
ver[1]: 5 (# 00B8AFF4)
ver[2]: 10 (# 00B8AFF8)
var addr 1: CCCCCCCC
var addr 2: 00B85BF0
var[0] addr = 00B8AFF0
Received arg addr: 00B85BF0
Freeing arg[0] = 00B8AFF0
In-function ver[0] = 0
In-function ver[0] = 2
ver[0] new value: -17891602
So far so good, now break.
I have tested your code on gcc 4.6.3 and find that this program does not have any memory leaks using valgrind. And when I delete the line "free(ver)" in main, the program runs perfectly and does not have any memory leak either. I think free_test routine has successfully freed those two malloc you have in main. As for why there is not any coredump pops out when freeing the var again in the program, it depends on different OS implementation.
Test it with valgrind and you will find it useful if you want to check memory leaks involving malloc and free.
Use
"* (*(arg+0)+0)"
instead of [][].
Syntax like [][]...[] only dereference pointer once. Each [] only change the semantic of pointer (how many location it jumps when +1), have nothing to do with dereference times.
void free_test(int** arg){
printf("\tReceived arg addr: %p\n",arg);
printf("\tFreeing arg[0] = %p\n",arg[0]);
//And, just to MAKE SURE that arg[0] is ver, we do this:
printf("\tIn-function ver[0] = %d\n",arg[0][0]);
arg[0][0] = 2;
// ^^^^^^^^^^^^^^ here, arg[0][0] is the same as arg[0], so arg[0] is changed, not the location arg[0] points to.
printf("\tIn-function ver[0] = %d\n",arg[0][0]);
free(arg[0]); //This one doesn't work...
free(arg); //This one works though.
}
Why this comment in your code?
free(arg[0]); //This one doesn't work...
I think it did work, and it freed the data var points to, and then you freed it again.
Your debug data shows
ver addr 2: 00B8AFF0
Freeing arg[0] = 00B8AFF0
If you comment out the first time you freed it, it still fails?
and you used it after freeing it the first time:
printf("ver[0] new value: %d\n", ver[0]); /// but you already freed that
Try using
void *xmalloc(int s) {
char *ret = malloc(s);
printf("malloc(%d)==%p\n", s, ret);
return ret;
}
void xfree(void *b) {
printf("free(%p)\n", b);
free(b)
return;
}
#define malloc xmalloc
#define free xfree
It's been a long time since I worked in C.
Initialize your variables.
int** var = NULL;
int* ver = NULL;
Before you free a block of data, set it to all zeros (or some other value).
memset(void_ptr, 0, sizeof_your_data);
It's a LOT easier to read your code if you delete all those print statements... though I know they are useful for debugging... try it (make a backup first).
Related
So I'm building a virtual machine, and trying to make it as cross platform as possible, and suddenly encountering a strange error. There is a let instruction for my machine, which allocates memory for a variable in the memory of the machine and assign that variable with a value. In short, the let function calls getAddress to get the address of the variable. getAddress checks if the variable is already defined, and returns the address. If the variable is not defined, getAddress calls memallocate to allocate memory for the variable, and returns the address. Here is the definition of the functions :
static uint16_t memallocate(Machine *m, char *symbol){
uint16_t allocationAddress = getFirstFree(*m);
SymbolTable *newSymbol = (SymbolTable *)malloc(sizeof(SymbolTable));
newSymbol->symbolName = strdup(symbol);
newSymbol->next = NULL;
newSymbol->mema = allocationAddress;
if(m->symbolTable==NULL){
m->symbolTable = newSymbol;
}
else{
SymbolTable *temp = m->symbolTable;
while(temp->next!=NULL)
temp = temp->next;
temp->next = newSymbol;
}
m->memory[allocationAddress].acquired = 1;
m->memory[allocationAddress].data.value = 0;
m->occupiedAddress++;
return allocationAddress;
}
uint16_t getAddress(Machine *m, char *symbol){
SymbolTable *table = m->symbolTable;
while(table!=NULL){
if(strcmp(symbol, table->symbolName)==0){
return table->mema;
}
table = table->next;
}
uint16_t address = memallocate(m, symbol); // Here is the segfault happening
return address;
}
This code compiles and runs pretty well on Linux, but on Windows I'm getting a segfault on the memallocate call. Since memallocate is directly passed the arguments of getAddress, and the arguments both being a pointer, they shouldn't change. But while debugging through CLion, I'm seeing gibberish arguments to the memallocate call, which is indicating some kind of stack violation(may be). Again, it is ONLY happening in Windows. Can anybody tell me what is going wrong with my code?
Full code for the project can be found at GitHub.
I took your code and run it on linux through valgrind:
==13768== Conditional jump or move depends on uninitialised value(s)
==13768== at 0x109ABE: getAddress (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x10B714: let (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x109425: run (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x109F64: main (in /home/vonaka/VirtualMachine/machine)
==13768== Uninitialised value was created by a heap allocation
==13768== at 0x4C2BE7F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd
==13768== by 0x109C2F: main (in /home/vonaka/VirtualMachine/machine)
==13768==
So (luckily for us) it's not a Windows specific problem. The trick is that on the first call of getAddress (when m->symbolTable is NULL) you call getFirstFree(*m) at the beginning of memallocate, but look at this function:
static uint16_t getFirstFree(Machine m) {
uint16_t add = 0;
while(m.memory[add].acquired)
add++;
return add;
}
m.memory[i].acquired for i between 0 and number_of_instructions_in_your_input_file - 1are all equal to 1 as you initialize them in writeInstruction, but m.memory[number_of_instructions_in_your_input_file].acquired is not initialized yet.
So something like this will resolve your problem:
void writeInstruction(Machine *m, uint16_t add, Instruction ins) {
m->memory[add].acquired = 1;
m->memory[add].type = INSTRUCTION;
m->memory[add].data.instruction = ins;
m->occupiedAddress++;
if(add + 1 < NUM_MEM)
m->memory[add + 1].acquired = 0;
}
Or maybe this is more elegant (if it's works):
static uint16_t getFirstFree(Machine m) {
uint16_t add = 0;
while (m.memory[add].acquired && add < m.occupiedAddress)
add++;
return add;
}
Edit:
First of all about your comment:
By default, the members of the structure is initialised as 0
It's just not true!
Now about why you have segfault without malloc and how it's connected with valgrind's warning.
You have variable m of type Machine and some other variables in the stack, m contains Cell memory[NUM_MEM] and there is acquired in each Cell (which are not initialized!). Your input file contains let's say 88 instructions, so first 88 acquired will be correctly initialized after 88 calls of writeInstruction. Then program start to execute your instructions by calling some functions including memallocate and getFirstFree. In this loop:
while(m.memory[add].acquired)
add++;
for any add m.memory[add].acquired very likely can be different from 0, so once add is equal to NUM_MEM you have segfault.
Why it's not happening with malloc? Simply because you are lucky (but it's not a good luck), your heap is 'cleaner' than stack. Why it's happening only in Windows? Because this time you were not so lucky (I don't have segfault even in Windows).
I have an issue with my pointer to a structure variable. I just started using GDB to debug the issue. The application stops when it hits on the line of code below due to segmentation fault. ptr_var is a pointer to a structure
ptr_var->page = 0;
I discovered that ptr_var is set to an invalid memory 0x0 after a series of function calls which caused the segmentation fault when assigning the value "0" to struct member "page". The series of function calls does not have a reference to ptr_var. The old address that used to be assigned to ptr_var is still in memory. I can still still print the values of members from the struct ptr_var using the old address. GDB session below shows that I am printing a string member of the struct ptr_var using its address
(gdb) x /s *0x7e11c0
0x7e0810: "Sample String"
I couldn't tell when the variable ptr_var gets assigned an invalid address 0x0. I'm a newbie to GDB and an average C programmer. Your assistance in this matter is greatly appreciated. Thank you.
What you want to do is set a watchpoint, GDB will then stop execution every time a member of a struct is modified.
With the following example code
typedef struct {
int val;
} Foo;
int main(void) {
Foo foo;
foo.val = 5;
foo.val = 10;
}
Drop a breakpoint at the creation of the struct and execute watch -l foo.val Then every time that member is changed you will get a break. The following is my GDB session, with my input
(gdb) break test.c:8
Breakpoint 3 at 0x4006f9: file test.c, line 8.
(gdb) run
Starting program: /usr/home/sean/a.out
Breakpoint 3, main () at test.c:9
9 foo.val = 5;
(gdb) watch -l foo.val
Hardware watchpoint 4: -location foo.val
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val
Old value = 0
New value = 5
main () at test.c:10
(gdb) cont
Continuing.
Hardware watchpoint 4: -location foo.val
Old value = 5
New value = 10
main () at test.c:11
(gdb) cont
If you can rerun, then break at a point where ptr_var is correct you can set a watch point on ptr_var like this: (gdb) watch ptr_var. Now when you continue every time ptr_var is modified gdb should stop.
Here's an example. This does contain undefined behaviour, as I'm trying to reproduce a bug, but hopefully it should be good enough to show you what I'm suggesting:
#include <stdio.h>
#include <stdint.h>
int target1;
int target2;
void
bad_func (int **bar)
{
/* Set contents of bar. */
uintptr_t ptr = (uintptr_t) bar;
printf ("Should clear %p\n", (void *) ptr);
ptr += sizeof (int *);
printf ("Will clear %p\n", (void *) ptr);
/* Bad! We just corrupted foo (maybe). */
*((int **) ptr) = NULL;
}
int
main ()
{
int *foo = &target1;
int *bar = &target2;
printf ("&foo = %p\n", (void *) &foo);
printf ("&boo = %p\n", (void *) &bar);
bad_func (&bar);
return *foo;
}
And here's a gdb session:
(gdb) break bad_func
Breakpoint 1 at 0x400542: file watch.c, line 11.
(gdb) r
&foo = 0x7fffffffdb88
&boo = 0x7fffffffdb80
Breakpoint 1, bad_func (bar=0x7fffffffdb80) at watch.c:11
11 uintptr_t ptr = (uintptr_t) bar;
(gdb) up
#1 0x00000000004005d9 in main () at watch.c:27
27 bad_func (&bar);
(gdb) watch foo
Hardware watchpoint 2: foo
(gdb) c
Continuing.
Should clear 0x7fffffffdb80
Will clear 0x7fffffffdb88
Hardware watchpoint 2: foo
Old value = (int *) 0x60103c <target1>
New value = (int *) 0x0
bad_func (bar=0x7fffffffdb80) at watch.c:18
18 }
(gdb)
For some reason the watchpoint appears to trigger on the line after the change was made, even though I compiled this with -O0, which is a bit of a shame. Still, it's usually close enough to help identify the problem.
For such kind of problems I often use the old electric fence library, it can be used to find bug in "software that overruns the boundaries of a malloc() memory allocation". You will find all the instructions and basic usage at this page:
http://elinux.org/Electric_Fence
(At the very end of the page linked above you will find the download link)
I want to skip a line in C, the line x=1; in the main section using bufferoverflow; however, I don't know why I can not skip the address from 4002f4 to the next address 4002fb in spite of the fact that I am counting 7 bytes form <main+35> to <main+42>.
I also have configured the options the randomniZation and execstack environment in a Debian and AMD environment, but I am still getting x=1;. What it's wrong with this procedure?
I have used dba to debug the stack and the memory addresses:
0x00000000004002ef <main+30>: callq 0x4002a4 **<function>**
**0x00000000004002f4** <main+35>: movl $0x1,-0x4(%rbp)
**0x00000000004002fb** <main+42>: mov -0x4(%rbp),%esi
0x00000000004002fe <main+45>: mov $0x4629c4,%edi
void function(int a, int b, int c)
{
char buffer[5];
int *ret;
ret = buffer + 12;
(*ret) += 8;
}
int main()
{
int x = 0;
function(1, 2, 3);
x = 1;
printf("x = %i \n", x);
return 0;
}
You must be reading Smashing the Stack for Fun and Profit article. I was reading the same article and have found the same problem it wasnt skipping that instruction. After a few hours debug session in IDA I have changed the code like below and it is printing x=0 and b=5.
#include <stdio.h>
void function(int a, int b) {
int c=0;
int* pointer;
pointer =&c+2;
(*pointer)+=8;
}
void main() {
int x =0;
function(1,2);
x = 3;
int b =5;
printf("x=%d\n, b=%d\n",x,b);
getch();
}
In order to alter the return address within function() to skip over the x = 1 in main(), you need two pieces of information.
1. The location of the return address in the stack frame.
I used gdb to determine this value. I set a breakpoint at function() (break function), execute the code up to the breakpoint (run), retrieve the location in memory of the current stack frame (p $rbp or info reg), and then retrieve the location in memory of buffer (p &buffer). Using the retrieved values, the location of the return address can be determined.
(compiled w/ GCC -g flag to include debug symbols and executed in a 64-bit environment)
(gdb) break function
...
(gdb) run
...
(gdb) p $rbp
$1 = (void *) 0x7fffffffe270
(gdb) p &buffer
$2 = (char (*)[5]) 0x7fffffffe260
(gdb) quit
(frame pointer address + size of word) - buffer address = number of bytes from local buffer variable to return address
(0x7fffffffe270 + 8) - 0x7fffffffe260 = 24
If you are having difficulties understanding how the call stack works, reading the call stack and function prologue Wikipedia articles may help. This shows the difficulty in making "buffer overflow" examples in C. The offset of 24 from buffer assumes a certain padding style and compile options. GCC will happily insert stack canaries nowadays unless you tell it not to.
2. The number of bytes to add to the return address to skip over x = 1.
In your case the saved instruction pointer will point to 0x00000000004002f4 (<main+35>), the first instruction after function returns. To skip the assignment you need to make the saved instruction pointer point to 0x00000000004002fb (<main+42>).
Your calculation that this is 7 bytes is correct (0x4002fb - 0x4002fb = 7).
I used gdb to disassemble the application (disas main) and verified the calculation for my case as well. This value is best resolved manually by inspecting the disassembly.
Note that I used a Ubuntu 10.10 64-bit environment to test the following code.
#include <stdio.h>
void function(int a, int b, int c)
{
char buffer[5];
int *ret;
ret = (int *)(buffer + 24);
(*ret) += 7;
}
int main()
{
int x = 0;
function(1, 2, 3);
x = 1;
printf("x = %i \n", x);
return 0;
}
output
x = 0
This is really just altering the return address of function() rather than an actual buffer overflow. In an actual buffer overflow, you would be overflowing buffer[5] to overwrite the return address. However, most modern implementations use techniques such as stack canaries to protect against this.
What you're doing here doesn't seem to have much todo with a classic bufferoverflow attack. The whole idea of a bufferoverflow attack is to modify the return adress of 'function'. Disassembling your program will show you where the ret instruction (assuming x86) takes its adress from. This is what you need to modify to point at main+42.
I assume you want to explicitly provoke the bufferoverflow here, normally you'd need to provoke it by manipulating the inputs of 'function'.
By just declaring a buffer[5] you're moving the stackpointer in the wrong direction (verify this by looking at the generated assembly), the return adress is somewhere deeper inside in the stack (it was put there by the call instruction). In x86 stacks grow downwards, that is towards lower adresses.
I'd approach this by declaring an int* and moving it upward until I'm at the specified adress where the return adress has been pushed, then modify that value to point at main+42 and let function ret.
You can't do that this way.
Here's a classic bufferoverflow code sample. See what happens once you feed it with 5 and then 6 characters from your keyboard. If you go for more (16 chars should do) you'll overwrite base pointer, then function return address and you'll get segmentation fault. What you want to do is to figure out which 4 chars overwrite the return addr. and make the program execute your code. Google around linux stack, memory structure.
void ff(){
int a=0; char b[5];
scanf("%s",b);
printf("b:%x a:%x\n" ,b ,&a);
printf("b:'%s' a:%d\n" ,b ,a);
}
int main() {
ff();
return 0;
}
I am attempting to tackle college worksheet on C programming (no marking for it, just to improve our learning). What we're meant to do is get a few details about shipping docks. I decided to use structures for this.
My code is below, what I need help with is to print out the information (to see if its working) of whats at the location of the shipyards .run.
Everything compiles and according to the debugger shipyard1.run and shipyard2.run point to different locations, but I can not see the values.
int main(int argc, char** argv)
{
typedef struct dockInfo
{
int dockCode;
int dockLength;
}dckDetails;
typdef struct shipyard
{
char dockName[20];
/* however big this number is thats how many dockInfo structs are needed.*/
int numOfDocks;
dckDetails *run; //points to the array of dockInfo structs
};
struct dockInfo *arrayD; // the array to hold all the dockInfo structs
struct dockInfo tempo; // the temporary dockInfo struct to take in the details
struct shipyard shipyard1;
struct shipyard shipyard2;
/**
* the variables for shipyard1 and shipyard2 are then assigned
**/
int i;
for (i=0;i<shipyard1.numOfDocks;i++)
{
arrayD=calloc(shipyard1.numOfDocks,100); // allocate a new bit of memory for arrayD
tempo.dockCode=45*i;
tempo.dockLength=668*i;
arrayD[i]=tempo; //the element of arrayD becomes tempo.
}
shipyard1.run=arrayD; //make shipyard1.run point to the location of arrayD.
for (i=0;i<shipyard2.numOfDocks;i++)
{
arrayD=calloc(shipyard2.numOfDocks,100); // allocate a new bit of memory for arrayD
tempo.dockCode=1234*i;
tempo.dockLength=1200*i;
arrayD[i]=tempo; //the element of arrayD becomes tempo.
}
shipyard2.run=arrayD; //make shipyard2.run point to the new location of arrayD.
int elementTest1; // need element1test to be shipyard1.run[0].dockLength;
int elementTest2; // need element2test to be shipyard2.run[1].dockCode;
return (EXIT_SUCCESS);
}
It should be noted that I have left a lot of code out because I have yet to write it. I have used static examples for the moment (shipyard1 and shipyard2) but in the future I am going to implment a 'load info from file' feature.
Any help would be greatly appreciated and please excuse my English if it's poor, English is not my first language.
You have calloc() inside a for loop twice. Both times you're losing the address returned.
for () {
addr = calloc();
addr[i] = ...
}
the second time through the loop, the addr you got on the first time is gone (you got yourself a memory leak), the value you saved there is gone too.
Move the calloc() outside the loop ... and remember to free() the memory when you no longer need it
addr = calloc();
for () {
addr[i] = ...
}
free(addr);
Some feedback:
The memory allocation parts with calloc should occur outside the loop. Now you allocate it, and then loose track of it in the next iteration because new memory is allocated and assigned.
memory you allocate should be freed somewhere with free
shipyard1.numOfDocks (same for shipyard2) is unitialized when you use it, it may be a random number (which means you have an undefined number of loop iterations, and allocate an undefined amount of memory).
Good luck!
Others have made some very good points, and you should fix your code according to them. So far, no one seems to have seen that the call to calloc() is wrong. Instead of:
arrayD=calloc(shipyard1.numOfDocks,100);
it should be:
arrayD = calloc(shipyard1.numOfDocks, sizeof *arrayD);
You want shipyard1.numOfDocks objects, each of size equal to sizeof *arrayD.
In fact, as mentioned below, you don't need to set the memory allocated to all-zeros, so you can replace calloc() by malloc():
arrayD = malloc(shipyard1.numOfDocks * sizeof *arrayD);
(Be sure to #include <stdlib.h>, whether you call calloc() or malloc().)
I have some minor comments about style:
you don't need the typedef. You can write struct dockInfo instead of dckDetails. If you do keep the typedef, you should be consistent, and use the typedef name everywhere. You use struct dockInfo most of the time, and then use dckDetails once. Your usage suggests that you probably weren't comfortable declaring a pointer to the struct. However, struct dockInfo *run is a completely valid declaration.
you don't need the tempo object. You can instead do: arrayD[i].dockCode = 45*i; arrayD[i].dockLength = 668*i;
Unless you're running C99, you can't declare variables after statements in a block. So you should move the declarations for elementTest1 and elementTest2 to the top of main(), with other declarations.
return is a statement, not a function, so the parentheses are not needed.
Since you overwrite the memory allocated immediately, and don't need it to be zero, you can replace calloc() call by a suitable call to malloc().
As I said, these are minor comments. Your main problems lie with the wrong use of calloc, etc.
I shortened the variable names and re-wrote this to do what I think you are interested in. I also added display of the addresses the data is stored in.
Generally, when I try to understand something in the arrays and pointers world, I make the simple case work - an embedded array (my yard1) and then do the pointer thing after that (yard2, yard3)
You'll note each set of data has different start points, two add i for each point, one multiplies by i for each point.
#include <libc.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_DOCKS 100
int main(int argc, char** argv)
{
struct dock
{
int code;
int length;
};
struct yard
{
char name[20];
int numDocks;
struct dock arDocks[MAX_DOCKS]; //an array of dock structs
};
struct yard_2
{
char name[20];
int numDocks;
struct dock *run; //points to the array of dock structs
};
/* data within main function */
struct dock *arrayD; // pointer to dock structs
struct yard yard1;
struct yard_2 yard2;
struct yard_2 yard3;
int i;
char temp[] = "2 draY";
strcpy( yard2.name, temp ); /* temp is only persistant in main... */
strcpy( yard1.name, "Yard 1");
strcpy( yard3.name, "3 y 3 a 3 r 3 d 3");
yard1.numDocks = MAX_DOCKS; /* or so I guess.. */
yard2.numDocks = MAX_DOCKS; /* or so I guess.. */
yard3.numDocks = MAX_DOCKS; /* or so I guess.. */
/* get some memory, init it to 0 */
arrayD = calloc( yard2.numDocks, sizeof( struct dock ) );
/* connect to the yard2 struct via "run", a pointer to struct dock */
yard2.run = arrayD;
/* without middleman... get more memory, init it to 0 */
yard3.run = calloc( yard3.numDocks, sizeof( struct dock ) );
/* at this point arrayD could be re-used to get another hunk.. */
/* fill in and display data .. */
for (i=0;i<yard1.numDocks;i++)
{
/* This sets all the memory for yard 1... */
yard1.arDocks[i].code = 45 + i;
yard1.arDocks[i].length = 668 + i;
/* so here are some ways to display the data */
printf("%d, %d %x %d %x - ",
i, yard1.arDocks[i].code, &(yard1.arDocks[i].code),
(yard1.arDocks[i].length), &(yard1.arDocks[i].length) );
/* This sets the memory for yard 2... */
yard2.run[i].code = 45 * i;
yard2.run[i].length = 668 * i;
/* Display through a pointer to a calloc'ed array of structs is the
same syntax as the embedded array of structs. The addresses of the
array are completely different - 0xbffff704 vs 0x800000 on my Intel-based iMac... */
printf("%d %x %d %x - ",
yard2.run[i].code, &(yard2.run[i].code),
yard2.run[i].length, &(yard2.run[i].length) );
yard3.run[i].code = 100 + i;
yard3.run[i].length = 2000 + i;
/* see where second calloc got its memory... */
printf("%d %x %d %x\n",
yard3.run[i].code, &(yard3.run[i].code),
yard3.run[i].length, &(yard3.run[i].length) );
}
/* data all filled in, more demos of how to get it back: */
printf( "%s, : 1\n", yard1.name );
printf( "%d, : numOfDocs \n", yard1.numDocks );
printf( "0x%x, : arDocks \n", yard1.arDocks );
int elementTest1 = yard1.arDocks[0].length;
int elementTest2 = yard1.arDocks[1].code;
int elementTest3 = yard2.run[0].length;
int elementTest4 = yard3.run[1].code;
printf( "elementTest1: yard1.arDocks[0].length %d\n", elementTest1 );
printf( "elementTest2: yard1.arDocks[1].code %d\n", elementTest2 );
printf( "elementTest3: yard2.run[0].length %d\n", elementTest3 );
printf( "elementTest4: yard3.run[1].code; %d\n", elementTest4 );
for (i=0; i< yard2.numDocks; i++ ) {
printf("%d %d %d _ ", i, yard2.run[i].length, yard2.run[i].code);
printf(" %d %d \n", yard3.run[i].length, yard3.run[i].code);
}
return (EXIT_SUCCESS);
}
Here's an edited example of the output, compile/build via cc, cmd line a.out:
Macintosh-6:interview Bill4$ cc
dockyard.c Macintosh-6:interview
Bill4$ a.out
0 45 bffff6f8 668 bffff6fc - 0 800000 0 800004 - 100 800400 2000 800404
1 46 bffff700 669 bffff704 - 45 800008 668 80000c - 101 800408 2001 80040c
2 47 bffff708 670 bffff70c - 90 800010 1336 800014 - 102 800410 2002 800414
:
Yard 1, : 1
100, : numOfDocs
0xbffff6f8, : arDocks
elementTest1: yard1.arDocks[0].length 668
elementTest2: yard1.arDocks[1].code 46
elementTest3: yard2.run[0].length 0
elementTest4: yard3.run[1].code; 101
0 0 0 _ 2000 100
1 668 45 _ 2001 101
2 1336 90 _ 2002 102
3 2004 135 _ 2003 103
:
99 66132 4455 _ 2099 199
Macintosh-6:interview Bill4$
I am trying to use a malloc of short, something like
typedef union _SOME_STRUCT_ {
struct {
USHORT u:4;
USHORT v:4;
USHORT w:4;
} x;
USHORT word;
} SOME_STRUCT, *PSOME_STRUCT;
PSOME_STRUCT p = malloc (sizeof (SOME_STRUCT));
if (p) {
p->x.u = 0;
}
free (p); // **** RANDOMLY CRASHING HERE ****
I am debugging for a couple of days and clueless,
Note(edited): Linux, and gcc Version 3.4.6 20060404
ISSUE FOUND USING VALGRIND
But then, I would like to document it here so that my fellow developers might be aware of such a situation ...
I had actually defined the structure as
typedef union _SOME_STRUCT_ {
struct {
USHORT u:4;
USHORT v:4;
USHORT w:4;
} x;
USHORT word;
} ALBUM, *PALBUM;
and some-where else in the code I had also defined
#define ALBUM "album"
And so, sizeof (ALBUM) was referring to the #define value rather than the typedef and hence the issue.
The thing that amazes me is,
Is this allowed in C?
Try to pass your program through valgrind , an open source program and totaly free, maybe it could help you to see where is the issue. Don't forget to compile with debug symbols: gcc -g [etc] .
Hope this help..
This version of the code works for me.
#include <stdio.h>
#define USHORT unsigned short
typedef union _SOME_STRUCT_ {
struct {
USHORT u:4;
USHORT v:4;
USHORT w:4;
} x;
USHORT word;
} SOME_STRUCT, *PSOME_STRUCT;
int
main(int c, char *argv[])
{
PSOME_STRUCT p = malloc (sizeof (SOME_STRUCT));
if (p) {
p->x.u = 0;
}
free (p); // **** Properly exiting after this ****
}
This is GDB debug from a Cygwin on Windows XP.
(gdb) p/x sizeof(PSOME_STRUCT)
$1 = 0x4
(gdb) p/x sizeof(p)
$2 = 0x4
(gdb) p/x sizeof(*p)
$3 = 0x2
(gdb) n
23 if (p) {
(gdb) p/x *p
$4 = {x = {u = 0xc, v = 0x4, w = 0x3}, word = 0x534c}
Ignore the values in $4, data is uninitialized.
Program exited normally.
Do you have something else in the code besides these lines?
Edit: and, free(0); is a valid operation.
Might be an alignment issue. Does it still crash if you do something like this:
struct {
USHORT u:4;
USHORT v:4;
USHORT w:4;
USHORT :4;
} x;
The problem is not with the code but something that is happening before or in another thread.
I would reduce sections of the program until it stops crashing and then add it back in step by step until you figure out what section is causing this. Depending on the OS/Platform you could also try some memory checking tools, valgrind/_crtdebug etc..
If this issue is happening where you could debug it you could start your debug session with a call to memcheck.
A cause for a crash for memory is most often heap or freeing the same pointer twice.
If you're doing stuff in between the malloc and free, you could be overrunning a different array by accident and corrupting your own stack
(if 'p' doesn't happen to be in a register, and you overrun a statically-allocated array and hit the place on the stack where 'p' is stored, you will then later attempt to free random crap, hence the segfault)
You're unconditionally calling free() without checking if the malloc succeeded, so if the malloc failed and p is a NULL pointer, then you're calling free(NULL).
Move the free inside the if (p) block.
This might not be the cause of the crashes, and shouldn't be if not memory-constrained, but is a bug nonetheless.
Added later: doh, free(NULL) is explicitly allowed, per http://www.opengroup.org/onlinepubs/009695399/functions/free.html -- sorry.
What if you put free(p) in your if? Maybe (unlikely) malloc is failing...