I'am working on a project for my programming class (teoretically in C++ but our professor isn't big fan of C++ solutions and C is better viewed by him). The project is to do simple queue with type given by user and the problem is with the following code:
#include <cstdlib>
#include <cstring>
#include <stdio.h>
typedef struct
{
int nKey;
int* pTab;
}Usertype;
Usertype* AllocateUsertype( );
void PrintUsertype( Usertype* pItem );
int main()
{
Usertype *pItem = AllocateUsertype();
printf( "nKey: %d, pTab: %d %d", pItem->nKey, pItem->pTab[0], pItem->pTab[1] );
pItem->nKey = 3;
PrintUsertype( pItem );
}
Usertype* AllocateUsertype( )
{
Usertype* pItem = NULL;
int* t = NULL;
t = (int*)malloc( 2*sizeof( int ) );
if( !t ) return NULL;
memset( t, 0, 2*sizeof( int ) );
Usertype Item = { 0,t };
pItem = &Item;
return pItem;
}
void PrintUsertype( Usertype* pItem )
{
printf( "nKey: %d, pTab: %d %d", pItem->nKey, pItem->pTab[0], pItem->pTab[1] );
}
When I allocate usertype it works well and the pItem is created as expected, but after I printf it it's seemes like pItem is no longer there and there's just garbage nKey number and there isn't any tab.
Is this problem because im allocating this data struct in memory wrongly and somehow t as a local variable for AllocateUsertype disapears at random moment? If yes can someone give me idea how to do it correctly?
As pointed out in the comments, the problem is that inside AllocateUsertype() you are returning a pointer to a local variable that won't exists anymore once the function returns.
The solution is to allocate a Usertype using malloc, just like you did for t, and then return its pointer.
Usertype* AllocateUsertype( )
{
Usertype* pItem = NULL;
pItem = (Usertype*)malloc(sizeof(Usertype));
if (!pItem) return NULL;
int* t = NULL;
t = (int*)malloc( 2*sizeof( int ) );
if( !t ) return NULL;
memset( t, 0, 2*sizeof( int ) );
pItem->nKey = 0;
pItem->pTab = t;
return pItem;
}
Related
So i created a program that makes a stack and all of its operations, using a structure called stack.
Structure:
typedef struct {
int *v; /* contents of the stack */
int cap; /* capacity of v, i.e. how many elements can fit in v */
int sz; /* number of elements currently stored in v */
} stack;
The program works fine but when i use fsantize it says that there is a buffer overflow on the heap in the Push function and i dont understand why because ive reallocated the bytes that i needed and freed the ones that i didnt need.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int *v; /* contents of the stack */
int cap; /* capacity of v, i.e. how many elements can fit in v */
int sz; /* number of elements currently stored in v */
} stack;
void init(stack * s)
{
s->v = (int*) calloc(4,sizeof(int));
s->cap = 4;
s->sz = -1;
}
int is_empty(stack * s)
{
if (s->sz == -1)
return 1;
else
return 0;
}
void push(stack * s, int e)
{
if (s->sz+1 <= s->cap)
{
s->sz++;
s->v[s->sz] = e;
}
else
{
int *nv;
s->cap++;
s->sz++;
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
s->v = nv;
s->v[s->sz] = e;
}
}
int pop(stack * s)
{
if (is_empty(s) == 0)
{
int top = s->v[s->sz];
s->sz--;
return top;
}
else
{
printf("Impossible the stack isn't empty\n");
return 0;
}
}
void destroy(stack * s)
{
//frees the stack bytes that were allocated
free(s->v);
free(s);
}
int main()
{
int i;
stack *pilha = (stack*) malloc(sizeof(stack));
init(pilha);
if (is_empty(pilha) == 1)
printf("The stack is empty\n");
pop(pilha);
for (i = 0; i<=4;i++)
push(pilha,i);
push(pilha,5);
printf("The top is:%d\n",pilha->v[pilha->sz]);
if (is_empty(pilha) == 0)
printf("The stack isn't empty\n");
destroy(pilha);
return 0;
}
This line:
if (s->sz+1 <= s->cap)
contains a logical error: if s->sz+1 == s->cap you need more space. For example, if s->cap is 4 you only have space for 4 elements (indexes from 0 to 3), but in the case of s->sz == 3 you enter the if and the result is:
s->sz++; // 4
s->v[s->sz] = e; // s->v[4] overflow!
The right way to check would be if (s->sz+1 < s->cap), or even incrementing the value first:
s->sz++;
if (s->sz < s->cap) {
// ...
This:
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
s->v = nv;
Is also wrong. First, you are assuming that realloc() allocates new memory and that you need to free() the old buffer: you don't, realloc() does that for you if needed. Secondly, you are assuming that realloc() does not fail (as you are doing anywhere else in your code, malloc(), calloc(), etc). Third, you are casting the return value (again as you are doing anywhere else in your code), which you shouldn't (see Do I cast the result of malloc?).
What you should do instead is:
nv = realloc(s->v, sizeof(int)*s->cap);
if (nv == NULL) {
// Handle error, abort execution.
}
s->v = nv;
The check if (nv == NULL) should be done after every single call of malloc(), realloc() or calloc().
The function push is invalid.
This condition in the if statement
if (s->sz+1 <= s->cap)
can be a reason of undefined behavior. Let's assume for simplicity that s->cap is equal to 1. So you may push only one element without resizing the dynamically allocated array. So after pushing a new value s->sz will be equal to 0. And you may not push one more a new value without resizing the array. However the condition in the if statement will evaluate to true and you will write to memory outside the allocated array.
Also this code snippet
nv = (int*) realloc(s->v, sizeof(int)*s->cap);
free(s->v);
is invalid. In the case when the call of realloc was successful the memory pointed to by s->v was freed (or rreused). So the call of free again will invoke undefined behavior. That is whether there will be an attempt to free the already reallocated memory or the new allocated memory will be freed.
The function push can be defined for example the following way
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz+1 < s->cap ) )
{
s->v[++s->sz] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[++s->sz] = e;
}
}
return success;
}
But in any case it would be better to set the initial value to the data member sz to 0. In this case the data member would reflect the current size of the stack.
The return value of the function pop is ambiguous. The returned value 0 can be a valid value stored in the stack. Also the function shall shall not issue any message. It is the caller of the function that will decide whether to issue a message if any or not.
Also there is no need to allocate the object itself of the type stack dynamically. It can have the automatic storage duration and be a local variable.
And it is much better when the function that initialize the stack also has a second parameter that allows to specify the capacity of the created stack instead of using the magic number 4.
Below there is a demonstrative program that shows how the stack and its functions can be defined.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int *v; /* contents of the stack */
size_t cap; /* capacity of v, i.e. how many elements can fit in v */
size_t sz; /* number of elements currently stored in v */
} stack;
int init( stack * s, size_t capacity )
{
s->sz = 0;
s->cap = 0;
s->v = calloc( capacity, sizeof( int ) );
int success = s->v != NULL;
if ( success )
{
s->cap = capacity;;
}
return success;
}
int is_empty( const stack *s )
{
return s->sz == 0;
}
int push( stack *s, int e )
{
int success = 0;
if ( ( success = s->sz < s->cap ) )
{
s->v[s->sz++] = e;
}
else
{
int *nv = realloc( s->v, sizeof( int ) * ( s->cap + 1 ) );
success = nv != NULL;
if ( success )
{
s->v = nv;
++s->cap;
s->v[s->sz++] = e;
}
}
return success;
}
int pop( stack *s, int *value )
{
int success = !is_empty( s );
if ( success )
{
*value = s->v[--s->sz];
}
return success;
}
void destroy( stack *s )
{
free( s->v );
s->v = NULL;
s->cap = 0;
s->sz = 0;
}
int main( void )
{
stack pilha;
init( &pilha, 4 );
if ( is_empty( &pilha ) )
{
printf( "The stack is empty\n" );
}
const int N = 5;
for ( int i = 0; i < 5; i++ )
{
push( &pilha, i );
}
push( &pilha, N );
while ( ! is_empty( &pilha ) )
{
int value;
pop( &pilha, &value );
printf( "the current top value is %d\n", value );
}
destroy( &pilha );
if ( is_empty( &pilha ) )
{
printf("The stack isn't empty\n");
}
return 0;
}
The program output is
The stack is empty
the current top value is 5
the current top value is 4
the current top value is 3
the current top value is 2
the current top value is 1
the current top value is 0
The stack isn't empty
I'm reading and saving strings from a formatted file and for some reason I found out sscanf() changes testa_e->ident contents.
I have put some printf around and I found that the problem occurs right after sscanf(); I have also checked addresses of temp2, temp5 and testa_e by printing them but they are different.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define string 30
#define line 100
typedef const char *identifier;
struct nodo_id {
identifier ident;
struct nodo_id *next;
};
typedef struct nodo_id nodo_id;
nodo_id *testa_e = NULL;
void addent(const char *id_ent) {
if (testa_e == NULL) {
testa_e = malloc(sizeof(nodo_id));
testa_e->ident = id_ent;
testa_e->next = NULL;
} else {
nodo_id *curs = testa_e;
while (curs != NULL) {
curs = curs->next;
}
curs = malloc(sizeof(nodo_id));
curs->ident = id_ent;
curs->next = NULL;
}
}
int main() {
char temp[line];
char temp2[string];
char temp5[string];
fgets(temp, line, stdin);
while (strncmp(temp, "end", 3) != 0) {
if (strncmp(temp, "addent", 6) == 0) {
if (testa_e != NULL)
printf("\nbefore sscanf: %s\n", testa_e->ident);
sscanf(temp, "%s %s", temp5, temp2);
if (testa_e != NULL)
printf("\nafter sscanf: %s\n", testa_e->ident);
addent(temp2);
}
fgets(temp, line, stdin);
}
}
This code here reproduces the exact same problem; after launch write addent firstword and addent secondwordon terminal and right around sscanf it should show you that testa_e->ident content has changed, I'd like to know why and how to fix this, because I seriously have no idea...
In the function addent this loop
while(curs!=NULL){
curs=curs->next;
}
iterates until curs is equal to NULL.
Then you are changing the pointer
curs=malloc(sizeof(nodo_id));
curs->ident=id_ent;
curs->next=NULL;
The list itself was not changed. You changed only the local variable curs.
Change the loop the following way
while ( curs->next != NULL ){
curs = curs->next;
}
and then
curs->next = malloc( sizeof( nodo_id ) );
curs->next->ident = id_ent;
curs->next->next = NULL;
The other problem is that you are using pointers to a local array
char temp2[string];
//...
addent(temp2);
So the last that will be stored in the array will be pointed to by all nodes. You need to allocate dynamically memory for each string that will be stored in the list and assign the address to the data member ident. In this case you have to remove the qualifier const from its declaration.
Take into account that it is a bad idea to make a function depends on a global variable,
A better definition of the function addent can look the following way
struct nodo_id{
char *ident;
struct nodo_id* next;
};
typedef struct nodo_id nodo_id;
int addent( nodo_id **head, const char *id_ent )
{
nodo_id *new_nodo_id = malloc( sizeof( nodo_id ) );
int success = new_nodo_id != NULL;
if ( success )
{
new_nodo_id->ident = malloc( strlen( id_ent ) + sizeof( ( char )'\0' ) );
success = new_nodo_id->ident != NULL;
if ( ! success )
{
free( new_nodo_id );
}
else
{
strcpy( new_nodo_id->ident, id_ent );
new_nodo_id->next = NULL;
while ( *head != NULL ) head = &( *head )->next;
*head = new_nodo_id;
}
}
return success;
}
And the function can be called like
addent( &testa_e, temo2 );
Why in the function there is used the pointer to pointer to the head?
First of all if we want to change the original head we need to pass it by reference. Secondly in the loop
while ( *head != NULL ) head = &( *head )->next;
again the data member next of the last node is pointed to by the pointer. So we are changing not the local variable curs as in your implementation of the function but the data member next of the last node. So we are changing the list itself.
Pay attention to that defining such a typedef as
typedef const char* identifier;
is a bad practice.
The main problem is (besides the one #VladFromMoscow addressed in his answer), that in addent() you only store the pointer id_ent in your struct:
curs->ident=id_ent;
But that is nothing else but the address of temp2, so if you copy something else into temp2 by calling sscanf() you'll see the new value in testa_e->ident too.
Change the line form above to
curs->ident=strdup(id_ent);
to create a copy.
And don't forget to call free(curs->ident) when before you are freeing curs
I need help to write a function called find inside my program, which takes a key and a reference to an integer, fills in the reference with the appropriate value (if found), and returns 1 (true). If the key is not found, return 0 (false). You may assume that p already points to a valid location. So:
int find( char *key, int *p );
Can be called like this:
char *name = "Bob";
int data;
if( find( name, &data ))
printf( "Found %s. (S)he's %i\n\n", name, data );
else
printf( "\nCouldn't find %s\n\n", name );
This is the program I have:
#define TABLE_SIZE 7
#define NUM_INPUTS 7
int hash( char *s )
{
return strlen( s ) % TABLE_SIZE ;
}
typedef struct entry
{
char *key;
int val;
struct entry *next;
} entry;
entry* table[ TABLE_SIZE ] = { NULL };
void insert( char *s, int v )
{
int h = hash( s );
entry *t = (entry*) malloc( sizeof( entry ));
t->key = s;
t->val = v;
t->next = table[h];
table[h] = t;
}
int main()
{
char* keyList[] = { "Jaga", "Jesse", "Cos", "Kate", "Nash", "Vera",
"Bob" };
int valList[] = { 24, 78, 86, 28, 11, 99, 38 };
int i;
for( i=0; i<NUM_INPUTS; ++i )
insert( keyList[i], valList[i] );
/* Probably call function find right here */
return( 0 );
}
int find( char *key, int *p_ans )
{
}
Thank you.
Firstly you need to write a keycomp function prototype
int keycomp (struct data left,struct data right);
Return 0 for equals, -1 for L>R and 1 for R>L.
From the origin in your data space chain through comparing the test key to the stored keys.
Because you have a lot I control, ie knowing when a collision happens.
You could just try to store the test key if it goes straight in you know test key has no value stored. Should it collide you need to then do a keycomp against all colliding keys. Note key {2,rhubarb} may have the same hash as {37,dog}.
Remember to delete this newly created dummy test record.
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;
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.