I have a structure that contains a pointer to a byte array.
To set the pointer I’ve tried the following two ways:
1 Use malloc then memcpy byte array data (commented out in code below).
2 Simply copy pointer.
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
typedef struct _element
{
unsigned char *pValue;
int nLength;
} Element;
Element* ElementCreate(void)
{
Element *pElement = (Element*)malloc(sizeof(*pElement));
pElement->pValue = NULL;
pElement->nLength = 0;
return pElement;
}
void ElementDestroy(Element **ppElement)
{
Element *pElement = NULL;
if (!ppElement)
return;
pElement = *ppElement;
//free(pElement->pValue);
//pElement->pValue = NULL;
free(pElement);
*ppElement = NULL;
}
void ElementSetValue(Element *pElement, unsigned char *pValue, int nLength)
{
//pElement->pValue = (unsigned char*)malloc(nLength * sizeof(*(pElement->pValue)));
//if (!(pElement->pValue))
// return;
//memcpy(pElement->pValue, pValue, nLength);
pElement->pValue = pValue;
pElement->nLength = nLength;
}
void ElementWriteValue(const Element *pElement)
{
int nIndex = 0;
for (; nIndex < pElement->nLength; nIndex++)
printf("%02X ", pElement->pValue[nIndex]);
}
int main(void)
{
//unsigned char myValue[] = { 0x01, 0x02, 0x03 };
//int nLength = sizeof(myValue) / sizeof(myValue[0]);
Element *pElement = ElementCreate();
{
unsigned char myValue[] = { 0x01, 0x02, 0x03 };
int nLength = sizeof(myValue) / sizeof(myValue[0]);
ElementSetValue(pElement, myValue, nLength);
}
// How come this writes out correct value?
ElementWriteValue(pElement);
ElementDestroy(&pElement);
return 0;
}
(Error checks are omitted for brevity)
Which way is correct?
I’d expect 2 to fail because myValue will be destroyed after the “}” so
printf("%02X ", pElement->pValue[nIndex]);
would write out rubbish data but it seems to work OK. Why?
It is undefined behaviour, of which a subset is to "work correctly".
The array myValue is out of scope at the next }. At this point the memory location in which myValue was stored is available to be resused, but it may not be leaving it unchanged and hence the code appears to work.
The correct approach is to malloc(), memcpy() and free().
when we enter into
{
unsigned char myValue[] = { 0x01, 0x02, 0x03 };
int nLength = sizeof(myValue) / sizeof(myValue[0]);
ElementSetValue(pElement, myValue, nLength);
}
that mean a memory will be reserved for myValue. and when we leave it (after }) that mean the memory related to myValue is not reserved any more and it's free but the content is not changed. and that's why you have access to memory and its content is not changed.
If your application is multithread application then there is a big risk that the data related to myValue meory changes by another thread and in this case you have always access to the same memory space but you will find that the memory content changes
Related
I have a function that writes custom structs to some kind of "data block" (struct) that I created, which contains a void pointer that can store a custom struct. I created a function to write and to read to that specific void pointer but unfortunately, the first element of the returned struct always returns as "80" instead of it's original value. Here's the code:
#include <stdio.h>
#include <malloc.h>
typedef struct dataBlock {
void* dataObject;
} DataBlock;
typedef struct testingStruct {
int testingInt1;
int testingInt2;
}TestObject;
void dataWriter(DataBlock *dataBlock, void* inputObject, int objSize) {
if (objSize > 255) {
printf("Error. Maximum 255 Bytes of data can be stored.");
exit(0);
}
dataBlock->dataObject = malloc(objSize+1); // Allocates the size of dataObject plus one byte to store the size of the data Object.
((char*)dataBlock->dataObject)[0] = (char)objSize; //Stores the size of the data object to position 0 in the void*
for (int i = 1; i < objSize; ++i) {
((char*)dataBlock->dataObject)[i] = (char)((char*)inputObject)[i];
}
}
void* dataGetter(DataBlock *dataBlock) {
void* dataToReturn = malloc(((int)((char*)dataBlock->dataObject)[0])); // Creates Container to store read data using Void* Pos 0 in dataObject
for (int i = 1; i < (int)(((char*)dataBlock->dataObject)[0]); ++i) {
((char*)dataToReturn)[i] = (char)((char*)dataBlock->dataObject)[i]; //writes each byte of data to return to dataToReturn
}
return dataToReturn;
}
int main() {
TestObject *testObject = malloc(sizeof(TestObject));
testObject->testingInt1 = 74;
testObject->testingInt2 = 49;
DataBlock *dataBlockToStore = malloc(sizeof(DataBlock));
dataWriter(dataBlockToStore, testObject, sizeof(TestObject));
TestObject *testObjectCpy = dataGetter(dataBlockToStore); // Reads data from Block and generates another TestObject
printf("%d\n", testObjectCpy->testingInt1); // Should be 74
printf("%d\n", testObjectCpy->testingInt2); // Returned Correctly
return 0;
}
I am unsure, if I am either reading or writing the data in the wrong way but the first variable in the written testingStruct always returns a wrong value.
for (int i = 1; i < objSize; ++i) {
((char*)dataBlock->dataObject)[i] = (char)((char*)inputObject)[i];
Array indices are zero-based. You are skipping the first element.
You need to do e.g. (avoid i and 'l' in loops when adding 1.....)
for (int j = 0; j < objSize; ++j) {
((char*)dataBlock->dataObject)[j+1] = (char)((char*)inputObject)[j];
You could alternatively use memcpy.
You should also assert/fail if the size is above 255
Also, if you make dataBlock a char* you will need to perform less casting.
I am working with Esspresif ESP32 WROOM board. I have tried to analyse the error I get with GDB Hardware Debugger, but I only receive the line where the error occurs, no error description.
Here's my small program:
typedef unsigned char u08;
void app_main() {
static char *mac_str = "00:00:00:00:00:00";
static u08 mac_addr[6] = {0x1a, 0x11, 0xaf, 0xa0, 0x47, 0x11};
net_dump_mac(mac_addr);
}
void net_dump_mac(const u08 *in) {
int pos = 0;
for (int i=0; i<6; i++) {
byte_to_hex(in[i], (u08 *)(mac_str+pos));
pos += 3;
}
uart_send(mac_str);
}
void byte_to_hex(u08 in, u08 *out) {
out[0] = nibble_to_hex(in >> 4); // <= crash occurs here !
out[1] = nibble_to_hex(in & 0xf);
}
u08 nibble_to_hex(u08 in) {
if (in < 10)
return '0' + in;
else
return 'A' + in - 10;
}
Some idea what am I doing wrong here?
char *mac_str = "00:00:00:00:00:00"; assigns a literal string to mac_str. A literal is read-only on many architectures. Trying to modify it will result in the memory manager no allowing it, often causing a segfault or other exception to occur.
Instead, do:
char mac_str[] = "00:00:00:00:00:00";
This creates an array that is initialized with the literal on the right, which gets copied to your array. The array will be the size of the literal string, including the null terminator. This array variable is modifyable.
The code below crashes during runtime. I used a couple of online references to come up with the code, and since it compiles thought the issue was somewhere else. But I went over the rest of it and that seems to work fine.
ring_buffer.h
#ifndef RING_BUFFER_H /* Guard against multiple inclusion */
#define RING_BUFFER_H
#include <stddef.h> // Defines NULL
#include <stdbool.h> // Defines true
#include <stdlib.h> // Defines EXIT_FAILURE
#include <stdint.h> // Defines uint32_t
#include <string.h>
typedef struct{
uint8_t * buffer;
uint8_t head;
uint8_t tail;
uint8_t max_length;
}ring_buffer;
void buffer_init(ring_buffer *buff_ptr);
bool buffer_full(ring_buffer *buff_ptr);
bool buffer_empty(ring_buffer *buff_ptr);
bool buffer_write(ring_buffer *buffer, uint8_t data);
bool buffer_read(ring_buffer *buffer, uint8_t * data);
#endif /* _EXAMPLE_FILE_NAME_H */
ring_buffer.c
#include "ring.h"
//ring_buffer UART_buffer; this goes in UART.h
#define UART_RING_BUFFER_SIZE 16
void buffer_init(ring_buffer *buff_ptr)
{ // type casting cause malloc returns void pointer
buff_ptr = (ring_buffer*)malloc(sizeof(ring_buffer)); // assign address to the uart_ring_buffer of size ring_buffer
memset(&buff_ptr, 0x00, sizeof(buff_ptr)); // set all locations to NULL so that if read before write conditions occur, garbage data is not read
buff_ptr->buffer = (uint8_t*)malloc(UART_RING_BUFFER_SIZE * sizeof(uint8_t)); // data buffer assigned of size max_length
memset(&buff_ptr->buffer, 0x00, sizeof(uint8_t));
buff_ptr-> head = 0;
buff_ptr-> tail = 0;
buff_ptr-> max_length = UART_RING_BUFFER_SIZE;
}
bool buffer_write(ring_buffer *buff_ptr, uint8_t data)
{
int next = buff_ptr->head + 1; // increment head to point to location in which data will be written to
if(next >= buff_ptr->max_length)
next = 0;
if(next == buff_ptr->tail) //check for buffer full condition
return -1; // indicate write failed, buffer full
buff_ptr->buffer[buff_ptr->head] = data;
buff_ptr->head = next; // update head to point to current location
return 0; // indicates buffer write success
}
bool buffer_read(ring_buffer *buff_ptr, uint8_t *data)
{
int next = buff_ptr->tail+1;
if(next >= buff_ptr->max_length)
next = 0;
if(buff_ptr->head == buff_ptr->tail) // check for buffer empty
return -1; // indicates read failed, buffer empty
*data = buff_ptr->buffer[buff_ptr->tail];
buff_ptr->tail = next;
return 0;
}
bool buffer_full(ring_buffer *buff_ptr) //NOT PROPER LOGIC
{
int next = buff_ptr->head + 1; // increment head to point to location in which data will be written to
if(next >= buff_ptr->max_length)
next = 0;
if(next == buff_ptr->tail) //check for buffer full condition
return 1;
else
return 0;
}
bool buffer_empty(ring_buffer *buff_ptr)
{
if(buff_ptr->head == buff_ptr->tail) // check for buffer empty
return 1; // indicates read failed, buffer empty
return 0;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "ring.h"
ring_buffer UART_FIFO;
int main()
{
char x;
buffer_init(&UART_FIFO);
printf("data in goes here: ");
while (1)
{
scanf("%c",&x);
buffer_write(&UART_FIFO, x);
}
}
let me know if there are any obvious mistakes, kinda new to using pointers, have done verilog and FPGA related stuff previously.
I found the issue:
memset(&buff_ptr, 0x00, sizeof(buff_ptr));
Has to be:
memset(buff_ptr, 0x00, sizeof(ring_buffer));
buff_ptr = (ring_buffer*)malloc(sizeof(ring_buffer)); // assign address to the uart_ring_buffer of size ring_buffer
memset(&buff_ptr, 0x00, sizeof(buff_ptr)); // set all locations to NULL so that if read before write conditions occur, garbage data is not read
that buff_ptr is already a pointer passing reference of buff_ptr to memset doesn't do any good remove the &
memset(&buff_ptr, 0x00, sizeof(buff_ptr)); //
I'm working on a homework assignment and I need to basically create a character buffer. One of the functions I need to create is called "b_reset". It's purpose is to reinitialize the given buffer so that it will point to the first position in the char buffer. This is needed because later on, when a new char is added to the buffer, it needs to be added to the first position in the buffer.
This is the code I have thus far:
The struct:
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
The code:
int b_reset ( Buffer *pB )
{
Buffer *temp = NULL;
int i = 0;
int j = 1;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
temp = (Buffer*)malloc(sizeof(Buffer*));
if (temp == NULL)
{
return R_FAIL_1;
}
temp->ca_head = (char*)malloc(pB->capacity);
if (!temp->ca_head)
{
temp = NULL;
return R_FAIL_1;
}
for(i = 0;i < ca_getsize(pB);++i)
{
temp->ca_head[j] = pB->ca_head[i];
j++;
}
pB->ca_head = temp->ca_head;
//free(temp->ca_head);
//free(temp);
return 0;
}
}
My goal in this code was to create a temporary buffer that would basically shift over everything 1 time based on the actual given buffer. This would make the first position empty so another char could be added.
The problem I'm running into is that the original buffer doesn't seem to be returning the right values after I reset it.
When I do this for example:
temp->ca_head[0] = 'a';
temp->ca_head[1] = 'b';
temp->ca_head[2] = 'c';
temp->ca_head[3] = 'd';
temp->ca_head[4] = 'e';
b_reset(temp); //this will return the size as 0, when it's actually 5
//temp->ca_head[0] = 'i'; //if this is executed, it returns the size as 6
//and prints out the right values, but if it's not,
//it will not print out anything
printf("%d", ca_getsize(temp));
for(i = 0;i < ca_getsize(temp);++i)
{
printf("%c", temp->ca_head[i]);
}
I know something is going wrong here, but I'm not too sure what. Any suggestions would be greatly appreciated.
This code is based on your followup comment:
well I'm not trying to resize the buffer, I just want to create an
empty space in the first position, so basically shifting everything to
the right 1 time. The assumption is that there is a enough space in
the buffer to handle this process.
I don't think you need to do any malloc() ing beyond the initial one. You can just shift everything up in a loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define R_FAIL_1 1
#define BUFFER_SIZE 10
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
void allocate_buffer(Buffer *pB, int size)
{
pB->ca_head = malloc(size);
assert(pB->ca_head);
pB->capacity = size;
}
int ca_getsize( Buffer *pB)
{
return pB->capacity;
}
int b_reset ( Buffer *pB )
{
int i = 0;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
if ( ca_getsize(pB) <= 0 || pB->ca_head == NULL )
return R_FAIL_1;
}
// shift data up by 1 byte
for( i = ca_getsize(pB) - 1 ; i > 0;i-- )
{
pB->ca_head[i] = pB->ca_head[i-1];
}
pB->ca_head[0] = '\0';
return 0;
}
void print_buffer(Buffer *pB)
{
printf("capacity: %d \n", ca_getsize(pB));
for (int i = 0;i < ca_getsize(pB);++i)
{
printf("buffer(%d): [%d] ",i, pB->ca_head[i]);
}
printf("\n");
}
int main(void)
{
Buffer a_buffer;
allocate_buffer(&a_buffer,BUFFER_SIZE);
strcpy(a_buffer.ca_head,"abcdefgh");
print_buffer(&a_buffer);
int ret = b_reset(&a_buffer);
assert(ret == 0);
print_buffer(&a_buffer);
}
temp = (Buffer*)malloc(sizeof(Buffer*));
You need to allocate enough space to hold a Buffer, but you only allocate enough space to hold a pointer to a buffer. This should be:
temp = (Buffer*)malloc(sizeof(Buffer));
You are managing your memory incorrectly. You are allocating memory for a new Buffer struct when actually you only need to handle the memory of the ca_head member (if my interpretation of your homework problem is correct).
Each time you invoke b_reset, you will allocate memory for this struct that will not be released. If you don't handle your memory correctly, you will experience unexpected results as the one you are reporting in your question.
I suggest you to make a research on the function realloc and use it properly in your b_reset function.
Good luck with your homework.
Executive summary:
How can I define an arbitrarily-sized 2D array in C?
How can I determine the dimensions of that array at compile-time?
Full disclosure:
I'm writing code for an embedded controller. My application requires several lookup tables with different sizes which will all be used by one lookup function (a binary search). Here is what I have so far:
typedef struct
{
unsigned char count; // number of rows in the table
unsigned char width; // number of bytes in each row
const unsigned char * data; // pointer to table data[count][width]
}
LookupTable;
// returns the index of a value from within a table
unsigned char Lookup(unsigned long value, const LookupTable * table);
This part is working. What I would like to do now is define these tables in my source without having to manually enter the count and width constants. Here is what I am doing now:
#define T1_count 100
#define T1_width 3
const unsigned char table1_data[T1_count][T1_width] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
...
};
const LookupTable table1 = { T1_count, T1_width, table1_data };
Here is what I would like to be able to do (pseudo-code, since this array definition will not actually compile):
const unsigned char table1_data[] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
...
};
const LookupTable table1 =
{
get_count_expr(table1_data),
get_width_expr(table1_data),
table1_data
};
Obviously, get_count_expr and get_width_expr would have to be constant expressions of some sort, based on the size of the table, and not actual function calls.
To be clear, no part of this design is cast in stone. I'm just posting what I have so far, in the hopes that my intent is clear. Any ideas for improvement would be appreciated.
The "why":
These tables will be changed often, and it would make maintenance easier if entries could be added and removed, or the width of a table changed without having to manually adjust the constants each time. Having to keep track of the sizes manually can be error-prone and violates DRY. I'm looking for a better way.
Hmmm ... you can leave the leftmost size to the compiler:
#define T1_WIDTH 3
const unsigned char table1_data[][T1_WIDTH] =
{
{ 0x12, 0x34, 0x56 },
{ 0x12, 0x38, 0x12 },
/* ... */
};
T1_count = sizeof table1_data / sizeof *table1_data;
T1_width = sizeof *table1_data;
Well, it's ugly as hell, but I think the only way to do it within the constraints you've listed is to include the data in a string, and than have initialization code parse the string and generate the table. Ideally you'd do that in a script rather than use C to do it, but if it has to be in C, it has to be in C..
Note that in no way do I claim the following to be production code, but it's just a proof of concept...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define datatable "\
{ 0x12, 0x34, 0x56 },\
{ 0x14, 0x36, 0x10 },\
{ 0x13, 0x37, 0x11 },\
{ 0x12, 0x38, 0x12 }"
typedef struct
{
unsigned char count; // number of rows in the table
unsigned char width; // number of bytes in each row
unsigned char **data; // pointer to table data[count][width]
}
LookupTable;
int parsedatatable(char *data, LookupTable **table) {
char *p, *sp, save;
unsigned char *tabledata;
int count = 0, width = 0;
unsigned int tmp;
int i,j;
/* find count */
p = strstr(data,"{");
while (p) {
p++;
p = strstr(p, "{");
count++;
}
/* find width */
p = strstr(data, "{");
p++;
sp = strstr(p, "}");
if (sp != NULL) {
save = *sp;
*sp = '\0';
}
while (p) {
p = strstr(p, ",");
width++;
if (p != NULL) p++;
}
if (sp != NULL) {
*sp = save;
}
printf("Count = %d, width = %d\n",count, width);
tabledata = (unsigned char *)malloc(width*count*sizeof(unsigned char));
*table = (LookupTable *)malloc(sizeof(LookupTable));
(*table)->data = (unsigned char **)malloc(count*sizeof(unsigned char*));
for (i=0; i<count; i++) {
(*table)->data[i] = &(tabledata[i*width]);
}
(*table)->count = count;
(*table)->width = width;
p = data;
for (i=0; i<count; i++) {
p = strstr(p,"{");
if (!p) {
fprintf(stderr,"Fail (a) reading in data!: %s\n",data);
free((*table)->data);
free(tabledata);
free(*table);
return -1;
}
p++;
for (j=0; j<width; j++) {
printf("Scanning <%s>, ",p);
sscanf(p,"%x",&tmp);
printf("got %d\n",tmp);
(*table)->data[i][j] = tmp;
p = strstr(p,",");
if (!p && j<width-1) {
fprintf(stderr,"Fail (b) reading in data!: %d, %d, %s\n",i,j,data);
free((*table)->data);
free(tabledata);
free(*table);
return -1;
}
p++;
}
}
return 0;
}
void printtable(LookupTable *table) {
unsigned char i,j;
for (i=0; i<table->count; i++) {
printf("{");
for (j=0; j<table->width; j++) {
printf("%x ",table->data[i][j]);
}
printf("}\n");
}
return;
}
int main(int argc, char **argv) {
char *data;
LookupTable *table;
data = (char *)malloc(strlen(datatable)+1);
strcpy(data,datatable);
parsedatatable(data,&table);
printtable(table);
return 0;
}
Well, but who fills these tables with data? I think that generated sources are better solution.
Define table1_data inside a header. You can auto-generate that header using a script. I do something similar to that for some of my projects. I have a CSV file with data and a Ruby or Python script that generates a header from it.