The program crashes near assignment. How could I get it to work ? Thanks in advance. Sorry if it is repost. Could not find similar example anywhere.
#include <stdio.h>
typedef struct _kv
{
char *key;
char *value;
} _kv;
typedef struct _kvs
{
_kv *kv;
int size;
} _kvs;
main()
{
_kvs a;
a.kv[0].key = "This is key One";
a.kv[0].value = "This is value One";
a.size = 1;
printf("%s = %s\n", a.kv[0].key, a.kv[0].value);
}
You have created pointers but did not make room for the memory. You need to associate some memory with the pointers by possibly using malloc.
a.size = 1;
a.kv = malloc ( a.size * sizeof ( _kv ) );
int i;
const int string_sz = 80; // Or whatever else the string size should be
for ( i = 0; i < a.size; i++ )
{
a.kv[i].key = malloc ( string_sz );
a.kv[i].value = malloc ( string_sz );
}
strcpy ( a.kv[i].key, "This is key one" );
strcpy ( a.kv[i].value, "This is value one" );
Uninitialized pointers cannot be deferenced, you must first make sure they point at valid memory.
_kvs a;
a.kv = malloc(1 * sizeof *a.kv); /* Allocate a single _kv. */
a.kv[0].key = "key";
a.kv[0].value = "value";
a.size = 1;
Or you could use memory on the stack:
_kv my_kvs[1];
_kvs a;
a.kv = my_kvs;
a.kv[0].key = "key";
a.kv[0].value = "value";
a.size = 1;
Related
I have string array initialized like that:
char ** strArray;
if ( (strArray = malloc(sizeof(*strArray) + 3)) == NULL ) {
fprintf(stderr, "ls1: couldn't allocate memory");
//exit(EXIT_FAILURE);
}
strArray[0] = NULL;
strArray[0] = "111";
strArray[1] = "222";
strArray[2] = "1";
strArray[3] = "2";
I want to convert this string array to int array, like that:
int * toIntArray(char ** strArray) {
int size = getCharArraySize(strArray);
int intArray[size];
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return intArray;
}
int getCharArraySize(char ** strArray) {
int s = 0;
while ( strArray[s]) {
printf("Char array: %s.\n", strArray[s]);
s++;
}
return s;
}
And then I want to sort this int array.
I must have string array initilized like above (char ** strArray) and then convert this to int array and then sort it. Can anybody help my with that? I would ask about printed sorted integer in main function.
A few minor things to take note of in the question code:
char ** strArray;
if ( (strArray = malloc(sizeof(*strArray) + 3)) == NULL ) {
fprintf(stderr, "ls1: couldn't allocate memory");
//exit(EXIT_FAILURE);
}
If successful, the intention of the above code allocates memory to strArray sufficient for three char *'s. Specifically, strArray[0], strArray1 and strArray[2].
NOTE: As pointed out in Matt McNabb's comment below, it actually incorrectly allocates memory sufficient for one char *, and three extra bytes.
strArray[0] = NULL;
The above line sets sets the first pointer in the **strArray to point at NULL.
strArray[0] = "111";
The above code is odd. After just setting strArray[0] to point at NULL, the above line changes it to point to "111". Kind of makes setting it to NULL (in the first place) seem unnecessary.
strArray[1] = "222";
strArray[2] = "1";
The above two lines initialize the other two pointers in the strArray correctly.
strArray[3] = "2";
The above line attempts to initialize strArray[3], when that element of the array really doesn't exist. So, it is changing something to point to "2", but probably not with the expected result.
Perhaps the intent would be better served by changing the above code to:
char **strArray;
size_t strArrayElements=4;
if(NULL == (strArray = malloc((strArrayElements+1) * sizeof(*strArray))))
{
fprintf(stderr, "ls1: couldn't allocate memory");
exit(EXIT_FAILURE);
}
strArray[strArrayElements] = NULL;
strArray[0] = "111";
strArray[1] = "222";
strArray[2] = "1";
strArray[3] = "2";
As can be observed, the above code allocates 5 elements (strArrayElements+1) to the **strArray. The last element strArray[4] is initialized to NULL; a marker to indicate End-Of-List. Then the other 4 elements [0..3] are initialized.
Now shifting focus to:
int * toIntArray(char ** strArray) {
int size = getCharArraySize(strArray);
int intArray[size];
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return intArray;
}
The above code is successful at converting the strings to their integer forms, and storing them in intArray. However, the code is flawed when it attempts to return intArray to the caller. The intArray variable was declared as a local stack object. The return statement causes all such stack variables to become invalid; and allows the stack memory such variables were using to be used for other things.
Perhaps the the following code better represents what was intended. It allocates memory from the heap for intArray. This allocated memory can outlive the return statement:
int *toIntArray(char **strArray)
{
int size = getCharArraySize(strArray);
int *intArray = malloc(size * sizeof(*intArray));
int i;
for ( i = 0; i < size ; ++i)
{
intArray[i] = atoi(strArray[i]);
printf( "r[%d] = %d\n", i, intArray[i]);
}
intArray[size] = '\0';
return(intArray);
}
Spoiler code may be found here.
#include<stdio.h>
struct test_ {
char *device_name;
char *path_name;
};
typedef struct test_ test_t;
struct capabilities_ {
test_t tab[3];
int enable;
};
static test_t table[3] = {
{ "first", "john"},
{ "second", "mike"},
{ "third:", "vik" },
};
int main()
{
struct capabilities_ cap;
//cap.tab = table; ???
return 0;
}
I have a static array with the value, which I want to assign/copy to the same type/sized variable under the structure to table to cap.tab. Could you please help how to do that?
To do it at runtime, you can use user9000's approach, or something like this:
for (i = 0; i < 3; i++)
cap.tab[i] = table[i];
Or, convert your tab to use a pointer to test_t instead of array of test_t.
struct capabilities_ {
test_t *tab;
int enable;
};
int main()
{
struct capabilities_ cap;
cap.tab = table;
printf("%s\n", cap.tab[1].device_name);
return 0;
}
Or, if you are trying to do it at initialization, use one of the following:
struct capabilities_ cap = {
{
{ "first", "john" },
{ "second", "mike" },
{ "third:", "vik" },
},
1
};
Or this,
struct capabilities_ cap = {
{
table[0],
table[1],
table[2],
},
1
};
If you want to copy the strings, and not just the pointer to the strings, you'll need to allocate memory for each string in the target capabilities struct. Here is one way to do that
for (int i = 0; i < sizeof(table) / sizeof(test_t); i++)
{
size_t device_name_length = strlen(table[i].device_name);
size_t path_name_length = strlen(table[i].path_name);
size_t target_device_length = device_name_length + 1; // + 1 for null terminator
size_t target_path_length = path_name_length + 1; // + 1 for null terminator
cap.tab[i].device_name = (char*) malloc( target_device_length );
cap.tab[i].path_name = (char*) malloc( target_path_length );
strncpy_s(cap.tab[i].device_name, target_device_length, table[i].device_name, device_name_length);
strncpy_s(cap.tab[i].path_name, target_path_length, table[i].path_name, path_name_length);
}
If you don't care to make a deep copy, you can use the shallow copy mechanism shown by user9000 to just copy the pointers to the strings.
Also, if you use the mechanism above, don't forget to free if your capabilities is going to go out of scope and no longer be used :)
You can do it like so:
memcpy(cap.tab, table, sizeof (test_t) * (sizeof(table) / sizeof(test_t)));
This is just the same mechanism used in copying a string to another. Since you have the table size known, you can just do:
memcpy(cap.tab, table, 3 * sizeof(test_t));
The equivalent method of copying characters is like:
memcpy(str, str1, sizeof(char) * 4); // copy 4 of str1 into str
I need help in reviewing following code.
I am trying to store anything into memory allocated ( void *) and retrive the same.
Please take a look at the code and let me know if there is anything wrong, Or if it will not work, of if there is better approach to achieve the same.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct __c_object {
void *data;
size_t size;
} c_object;
c_object *new_c_object(void *inObject, size_t obj_size) {
c_object *tmp = (c_object*)malloc(sizeof(c_object));
tmp->size = obj_size;
tmp->data = (void*)malloc(obj_size);
memcpy ( tmp->data, inObject, obj_size);
return tmp;
}
void get_raw_c_object ( c_object *inObject, void **tmp) {
*tmp = (void*)malloc(inObject->size);
memcpy ( *tmp, inObject->data, inObject->size );
}
void delete_c_object ( c_object *inObject ) {
if (inObject ) {
free ( inObject->data );
free ( inObject);
}
inObject = ( c_object *)0;
}
int main() {
int in = 0;
c_object *co = new_c_object ( &in, sizeof(int));
void *ptrOut = (void*)0;
void *ptr = (void*)0;
get_raw_c_object( co , &ptrOut);
printf ( "Interger = [%d]\n", *(int*)ptrOut);
delete_c_object ( co );
float float_in = 10.99;
co = new_c_object ( &float_in, sizeof(float));
get_raw_c_object( co, &ptrOut);
printf ( "Float = [%f]\n", *(float*)ptrOut);
delete_c_object ( co );
int *ptr_int = ( int*) malloc ( sizeof ( int ));
in = 999;
ptr = ∈
co = new_c_object ( ptr, sizeof(int*));
get_raw_c_object( co,&ptrOut );
printf ( "Interger Pointer = [%d]\n", *(int*)ptrOut);
delete_c_object ( co );
char *inStr = "Hello Hello Hello";
char *inStrDup = _strdup (inStr);
co = new_c_object ( inStrDup, strlen(inStr) + 1);
free ( inStrDup );
get_raw_c_object( co ,&ptrOut);
printf ( "Character = [%s]\n", (char*)ptrOut);
delete_c_object ( co );
char *inStr2 = "Hello Hello Hello";
co = new_c_object ( inStr2, strlen(inStr2) + 1);
get_raw_c_object( co,&ptrOut );
printf ( "Character = [%s]\n", (char*)ptrOut);
delete_c_object ( co );
}
One Problem in the code it that get_raw_c_object( co, &ptrOut); allocates memory with malloc (returned by ptrOut) yet you never free that memory!
I don't exactly know what you are trying to achive but take a look at the following pseudo C/C++ code. Maybe it can help you:
typedef struct Variadic {
enum DataType type;
union {
char charData;
short shortData;
int intData;
unsigned int uintData;
char *charPtrData;
[...]
} data;
};
// functions for allocation and destruction
Variadic* new_variadic();
void delete_variadic(Variadic*);
// using the variadic
Variadic *a = new_variadic;
a->type = TYPE_INT;
a->data.intData = 10;
In case of a char* string delete_variadic would also delete the contained string.
You do really much copying with your objects. So I hope that all the types you want to store support being copied. One counter-example that comes to mind is a node of a doubly linked list, because there are some pointers outside that point to that exact address.
But as long as your data is not referenced from the outside, this works. You also need to make sure that your program has enough memory available, otherwise you run into undefined behavior as soon as malloc returns NULL.
In the delete_c_object function you don't need to zero out inObject. That statement has no effect at all.
The section for the integer pointer is missing one level of pointers. It looks just like the integer section.
ok, heres my code. I'm trying to pass an array of pointers to a structure to a function.
I need to dynamically allocate each structure and put a pointer to that structure in the array.
When I malloc the second time thru it gets a heap error.
HELP
#define MAXSTRUCTS 50
#define MAXBUFF 100
typedef struct {
char fullName[41];
char address[41];
char cityState[41];
char zipcode[11];
} Persons;
int readData(Persons *structPtrs[]);
int main(void) {
int totalStructs;
Persons *structPtrs[MAXSTRUCTS];
totalStructs = 0;
structPtrs[0] = NULL;
totalStructs = readData(structPtrs);
}
int readData(Persons *strptr[]) {
int tStructs = 0;
int recs;
char inRecord[MAXBUFF];
Persons *tmpPtr;
tStructs = 0;
for (recs=0; recs < MAXSTRUCTS; recs++) {
if (gets(inRecord) != NULL) {
strptr[recs] = (Persons *)malloc( sizeof(Persons));
tmpPtr = strptr[recs];
strncpy(tmpPtr->fullName,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->address,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->cityState,inRecord,MAXBUFF);
gets(inRecord);
strncpy(tmpPtr->zipcode,inRecord,MAXBUFF);
strptr[recs] = tmpPtr;
tStructs++;
}
else {
if ( recs = 0 ) {
exit (0);
}
recs=MAXSTRUCTS;
}
}
return(tStructs);
}
You are doing everything right in regard of passing an array of pointers and allocating memory. What leading to a heap corruption is incorrect usage of strncpy function. The arrays where you are trying to copy data to are slightly smaller than MAXBUFF in all cases. To fix this, you have to specify the size of destination array instead of MAXBUFF. For example, instead of:
strncpy(tmpPtr->fullName,inRecord,MAXBUFF);
... do (assuming that buffer is already filled with \0 symbols):
strncpy(tmpPtr->fullName,inRecord, sizeof(tmpPtr->fullName) - 1);
Also, using gets function is not recommended as well as it could easily lead to buffer overruns. Try using fgets instead.
Here is your modified example that works:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXSTRUCTS 2
#define MAXBUFF 100
typedef struct {
char fullName[41];
char address[41];
char cityState[41];
char zipcode[11];
} Persons;
int readData(Persons *structPtrs[]);
int main ()
{
int totalStructs;
int recs;
Persons *structPtrs[MAXSTRUCTS];
totalStructs = 0;
structPtrs[0] = NULL;
totalStructs = readData(structPtrs);
for(recs = 0; recs < totalStructs; ++recs) {
printf ("Record #%d - %s\n", recs + 1, structPtrs[recs]->fullName);
}
return 0;
}
int readData(Persons *strptr[])
{
int tStructs = 0;
int recs;
char inRecord[MAXBUFF];
Persons *tmpPtr;
tStructs = 0;
for (recs=0; recs < MAXSTRUCTS; ++recs) {
memset (inRecord, 0, sizeof(inRecord));
if (fgets(inRecord, sizeof (inRecord) - 1, stdin))
{
strptr[recs] = (Persons *)malloc(sizeof(Persons));
tmpPtr = strptr[recs];
memset (tmpPtr, 0, sizeof(Persons));
strncpy(tmpPtr->fullName,inRecord,sizeof(tmpPtr->fullName) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->address,inRecord,sizeof(tmpPtr->address) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->cityState,inRecord, sizeof(tmpPtr->cityState) - 1);
fgets(inRecord, sizeof (inRecord) - 1, stdin);
strncpy(tmpPtr->zipcode,inRecord, sizeof (tmpPtr->zipcode) - 1);
strptr[recs] = tmpPtr;
tStructs++;
} else {
if ( recs = 0 ) {
exit (0);
}
recs=MAXSTRUCTS;
}
}
return(tStructs);
}
int readDataToRecord( Persons *eachEntry[] ) {
int numEntries = 0 ;
Persons *tempPtr ;
for( int i=0 ; i < NUM_OF_RECORDS; ++i ) {
eachEntry[i] = ( Record * ) malloc( sizeof( Record ) ) ;
memset( eachEntry[i], 0, sizeof( Record ) ) ;
tempPtr = eachEntry[i] ;
fgets( tempPtr->firstName, sizeof( tempPtr->firstName ), stdin ) ;
fgets( tempPtr->secondName, sizeof( tempPtr->secondName), stdin ) ;
eachEntry[i] = tempPtr ;
++numEntries ;
}
return numEntries ;
}
This would also efficiently do the job. Once you have new record, you would any how have the memory allocated for each of its member. So you can directly fgets to that variable.
#Vlad : Please let me know if I am wrong.
I have defined struct like
typedef struct {
char *oidkey;
int showperf;
char oidrealvalue[BUFSIZE];
char *oidlimits;
} struct_oidpairs;
and I have array of struct
struct_oidpairs b[] ={{.....},....}
and I want to copy it to new struct array a[]
please help
Something like this:
memcpy(dest, src, sizeof(struct) * sizeof(src));
Your struct contains pointers as data members, this means you will have to roll out your own copy function that will do something sensible with the pointers. memcpy only works is all the data related to the struct is stored in the struct.
For real copy of the contents, follow Sjoerd's answer and then:
for (i = 0; i < sizeof(src); i++)
{
if (src[i].oidkey != NULL)
{
dest[i].oidkey = malloc(strlen(src[i].oidkey) + 1);
strcpy(dest[i].oidkey, src[i].oidkey);
}
if (src[i].oidlimits != NULL)
{
dest[i].oidlimits = malloc(strlen(src[i].oidlimits) + 1);
strcpy(dest[i].oidlimits, src[i].oidlimits);
}
}
You may consider memcpy if you are interested in speed.
Update:
Following harper's code, I
updated the code to check NULL
pointers
This is a quoted note from
gordongekko:
This solution will crash if
oidkey or oidlimits are != NULL and not
'\0'-terminated means not initialized
Makes NOT a deep copy:
struct_oidpairs b[] = {...};
size_t len = sizeof b/sizeof*b;
struct_oidpairs *a = malloc(sizeof b);
if( !a ) /* ERROR handling */
memcpy( a, b, sizeof b );
...
free( a );
or
while( len-- )
a[len] = b[len];
...
free( a );
maybe using :
for(int i=0; i<b.size() ;i++)
//I am not sure if this is the correct name for the size function
{
a[i]=b[i];
}