I am working on a little project where I am trying to emulate a CPU declaring and assigning values to variables, so far so good. So I defined the following structures for my CPU and Memory.
CPU (Can only keep track of 3 variables)
typedef struct variableReference{
char *tag;
void *reference;
}variableReference;
typedef struct CPU{
int variableCounter;
int instructionPointer;
variableReference dataDictionary[3];
void *currentContext;
}CPU;
Memory (and it's creation function). By the way, CPU.currentContext points to the memory.base on startup, then it can change.
typedef struct Memory{
void *base;
int size;
}Memory;
Memory memory_create(int size){
Memory newMemory;
newMemory.base = malloc(size);
newMemory.size = size;
return newMemory;
}
So the first thing I do is allocate a block of memory and keep track of it using the CPU current context pointer. I already have a function that asks the cpu to declare a variable (variables can only be integer) and another one that asks the cpu to assign that variable a value (int). To do this, I keep track of a limited amount of variable names and references in cpu.dataDictionary.
The variable declaring seems to work just fine, but the problem occurs when I try to assign that variable a value, which I do like this (e.g. a = 4;):
cpu_assignVariable(&myCPU,"a",4,&myMemory);
At that time, in my cpu.dataDictionary I have this in the first record {"a",0x804b008}, so all I should have to do is look for that position in the allocated memory block, and copy the value (integer 4), like this:
void *reference = cpu_dereferenceVariable(*myCPU,tag); // gets a's address
memory_write(reference,1,sizeof(value),(void *) value); // writes the value
now the memory_write implementation, where I get the Segmentation Fault (I have an offset of 1 because on the "reference" position I previously wrote the variable name:
int memory_write(void *base, int offset,int size,void *value){
memcpy(base+offset,value,size);
return 0;
}
I'd expect the memory block to look like this |a|0|0|0|4|x|x|...|x|, but all I get is a segmentation fault error. Any ideas???
Thanks in Advance!
Related
I'm writing a program that writes arrays and the information regarding them to a binary file.
My first approach was to call fwrite 4 times: once for general information regarding the array, once for the timestamp, once for the dimension of the array and once to write the array itself.
This approach worked as it is quite simple, but the execution times were too slow, seeing as the program is multithreaded and it writes to a SAS drive frequently, flooding the drive with requests which presented a bottleneck.
The new approach was to create an array of structs containing the information needed, my struct would be as follows:
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
}
During execution I would write the data to a buffer and when I had everything I need it would call a malloc to allocate array_data.data_array and copy everything from the buffer from inside a for loop.
The issue is when I call fwrite to write the whole struct, the first 3 members of the struct are written correctly, while the array is not and that is due to the address of the array not being contiguous, since it points to another place in memory after the malloc.
The best solution to this would be to declare the data_array as a static array, this way the fwrite would work as I need it to, but then I would have to call fwrite for every struct, instead of calling it once to write an array of structs, which would impact the performance, negating the use of the struct.
I've also tried using an array of dynamically allocated structs, by declaring my struct as follows:
struct array_data{
int information;
int timestamp;
int size;
int data_array[];
}
and allocating the array of structs using malloc, but the address of struct_array[1].information is not the one right after the struct_array[0].data_array[last_index], there seems to be another 5 bytes in between, so if I were to call fwrite with struct_array the data in the file would still be incorrect.
Is there a way to use structs to solve this issue or should I just stick with writing my arrays to the file as I did in the first place?
The following example creates, writes and reads your data. It is just a outline. Error checks on malloc, fread and fwrite ommitted:
#define N_DATA 10
#define N_INTS 5
struct array_data{
int information;
int timestamp;
int size;
int* data_array;
};
struct array_data arr[N_DATA];
void makeData(void){
int i;
for (i=0;i<N_DATA;i++) {
arr[i].data_array=malloc(N_INTS*sizeof(int));
arr[i].size= N_INTS;
}
}
void writeData(FILE *fp_out)
{
int i;
for (i=0;i<N_DATA;i++) {
fwrite(&arr[i],sizeof(arr[i]),1,fp_out);
fwrite(arr[i].data_array,arr[i].size*sizeof(int),1,fp_out);
}
}
void readData(FILE *fp_in)
{
int i= 0;
while(fread(&arr[i],sizeof(arr[i]),1,fp_in)==1) {
arr[i].data_array=malloc(arr[i].size*sizeof(int));
fread(arr[i].data_array,arr[i].size*sizeof(int),1,fp_in);
i++;
}
}
My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.
This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 5 years ago.
Hi all I am really new to C (just started this week), and want to make sure that I am not looking down the wrong rabbit home and hoping to perhaps get pointed to the right rabbit hole.
I create a struct:
#define MAX 64
#define ARRAY_SIZE 2048
struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char arr[ARRAY_SIZE][MAX]; // Creates an array of 2048 cells with string of length 63 max
};
int main(){
...
...
int variable = 30;
struct object l[variable]; //This is where the crash happens. But only when either variable is too large (for instance works on 15 just fine, but anything over 20 it crashes), or when Array_SIZE is too larger, for instance works fine with 1024 but 2048 crashes.
...
...
}
The error I get on crash is the following: Process returned -1073741571 (0xC00000FD) in the cmd window. And the following in the debugger in the IDE:
Program received signal SIGSEGV, Segmentation fault.
[Inferior 1 (process 12120) exited with code 030000000375]
Am I doing something obviously wrong with how I declare an array of structs? Why would large numbers not work but lower numebrs work?
Does the above error indicate I am accessing something out of bounds somewhere? Ive been up and down the code and cant seem to find any reason why larger numbers dont work and lower ones do. My memory footprint doesnt seem to be the issue, just a few megs of memory.
I need help with what to look for (I cant find any instances of accessing anything out of bounds, so I get the feeling Im not chasing the right rabbit and need to look for something else)? Or maybe Im doing something illegal for C without knowing it?
I think your program crashes because you statically allocate too much memory on the stack.
Try using the malloc or calloc function. It dynamically allocates memory on the heap instead e.g. :
struct object *l = malloc(variable*sizeof(struct object));
Don't forget to free it afterwards using the free function.
free(l);
You have a memory size problem, try to increase the memory size for your program.
And if you want to use big array size and so allocate a lot of memory, you shouldn't allocate statically but dynamically.
So you should use malloc
typedef struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char arr[ARRAY_SIZE][MAX];
} myObject ;
int variable = 30;
myObject *l = malloc(sizeof(myObject) * variable);
I do not advice you to declare an array of 2048 statically, so you should initiate your struct with a function.
typedef struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char *arr[MAX];
} myObject ;
myObject *createNewObject() {
myObject *toReturn = malloc(sizeof(myObject) * variable);
if (toReturn == NULL)
return NULL;
toReturn->arr = malloc(sizeof(char) * ARRAY_SIZE);
return (toReturn);
}
void freeMyObject(myObject *objectToFree)
{
if (objectToFree && objectToFree->arr =! NULL)
free(objectToFree->arr)
if (objectToFree)
free(objectToFree)
}
void main()
{
myObject *myNewObj = createNewObject()
// You can do some stuff with myNewObj but always verify the pointers
freeMyObject(myNewObj);
}
You should also debug with valgrind when you works with malloc, so you don't have memory loss or problems.
Hope I helped
Well the problem you had is - you have used automatic memory allocation. Due to constraint of size of automatic storage your program crashed - you asked for more than you should.
So what is the solution?
Static memory allocation:
Solution being
static struct object l[variable];
Dynamic memory allocation
struct object *ptr = malloc( sizeof *ptr * variable);
The storage of these allocation is different from automatic variables - so free from the size constraint . In this case you have to free the dynamically allocated memory. That's why you will get around the problem you have.
Statically allocate is not a confusion free term. All these types of variable will have different scope - lifetime. Standard never mentions about stack or heap . It is the implementation that follow these to store automatically allocated memory and dynamically allocated memory.
I am working on one Embedded C project. I am having trouble understanding the use of array and structure in code.
for example:
Structure:
struct example_struct{
char a;
char b;
char array[4];
}
Note: The default size for Int and char is 1 byte.
The compiler I am using provide the functionality of memory allocation for variables and other parameters using '#' symbol
for example:
Memory Allocation
int example # 0x125
// Compiler allocate the RAM memory location 0x125 to my variable "example"
Issue:
The person who coded this project have used the structure and array as given below
example.h
struct example_struct{
char a;
char b;
char array[4];
}
Memory.h
volatile struct example_struct node # 0x130 ;
//allocate memory location 0x130 - 0x135 to node
volatile char buffer[6] # 0x130;
//allocate memory location 0x130 - 0x135 to buffer
Question
1.Instead of using the pointer to access the member of structure is it appropriate to use the array placed on same memory location?
Does it cause the memory issue?
Would you please help me to understand the use of stuct and array in this particular situation.
Thank you
Kunal
The (weird) coder that developed that code was "simulating" an union to be able to access the same location as struct example_struct or byte per byte.
Like:
#pragma pack(1)
union struct_and_raw_byte_access
{
struct example_struct
{
char a;
char b;
char array[4];
}structured;
char buffer[sizeof(struct example_struct)];
};
#pragma pack()
int main(void)
{
union struct_ad_raw_byte_access temp;
int i;
temp.structured.a = 1;
temp.structured.b = 2;
temp.structured.array[0] = 3;
temp.structured.array[1] = 4;
temp.structured.array[2] = 5;
temp.structured.array[3] = 6;
for (i=0; i< sizeof(temp.buffer)/sizeof(temp.buffer[0]); i++)
printf("buffer[%d] = %d\n", i, temp.buffer[i]);
return 0;
}
1.Instead of using the pointer to access the member of structure is it appropriate to use the array placed on same memory location?
2.Does it cause the memory issue?
IMHO you cannot do that. It may work in some archs, but keep in mind that you are trusting the compiler to put everything packed and aligned.
Some compilers have packing directives (pragmas or parameteres), but it is much more safer to use an union.
Make sure that buffer is also a pointer, so allocating "buffer" to absolute address is the same like make a pointer to that address.
volatile char buffer[6] # 0x130;
//allocate memory location 0x130 - 0x135 to buffer
In your case, developer; I think; he decided to access strcutre elements using array for work with them in loop or something.
So, answering your questions:
No, It is not appropriate, as you said, it is better to make pointer and access this pointer by casting it to (char *)
If you know how you will use "buffer", no memory issue will happen. I mean make sure no out of index will happen.
Your comment "if I am declaring any global variable and watching it using debugger I can see the change in value. Even if I am not using them anywhere" probably means that you are looking at a hardware register of some IO controller.
The
volatile char buffer[6] # 0x130;
Is intended to map those IO controller addresses to a variable name in your embedded programming. That is the IO controller is presenting status and data at memory address 0x130 to 0x135 -- and the C program maps this to a symbolic value through the declaration.
Since the format of this area is determined by the IO controller (nothing you can do in your C code will change the format), you need to make sure that the strct and the example_struct is exactly 6 bytes long, or if not you have some padding which will kill you.
Test this using your debugger (if it is gdb use can use sizeof, but your debugger may differ)
Also, I recommend that you find some kind of documentation on what is on hardware address 0x130
I'm trying to implement a cache struct with pointers that point to "lower-level" set structs; It's supposed to simulate a cache. When I try to malloc the cache struct in the initCache function I get a seg fault. I've read other posts and I'm pretty sure it's not the syntax, but I'm new to C so I could be using the pointers wrong. I get a warning that L1cache may be uninitialized and I've also checked posts related to that but with no luck, trying what worked for others.
TO be clear the **sets in the cache definition is supposed to be an array of pointers where each pointer in the array points to a struct
The cache struct is defined as:
/* Struct representing the cache */
struct cache{
set **sets; /* Array of set pointers */
};
initCache is called in main as such:
cache* L1cache;
initCache(L1cache, nSets, setSize);
The code for initCache is:
void initCache(cache* c, int nSets, int setSize){
int i;
c->sets=malloc(nSets*sizeof(set*)); /* SEG FAULT HERE malloc space for array of pointers to each set */
for(i = 0; i < nSets; i++){
c->sets[i]=malloc(sizeof(set)); /* malloc space for each set */
initSet(c->sets[i],setSize);
}
return;
}
You need to initialize L1cache:
cache *L1cache = malloc(sizeof (cache));
Or you could just declare it as an ordinary variable:
char L1cache;
initCache(&L1cache, nSets, setSize);