i have a simple problem with my c code .... I want to call the variable with call by reference.
I have this function:
void createHeader(HEADER *yourHeader)
{
yourHeader = malloc(sizeof(HEADER));
if (yourHeader == NULL)
printError();
yourHeader->first = NULL;
yourHeader->last = NULL;
yourHeader->length = 0;
}
My main-call:
createHeader(&header);
if (header == NULL)
exit(-1);
Now I have the following problem: "The program '[6044] My-C-Project.exe' has exited with code -1 (0xffffffff)", so that means my function createHeader doens't work ... Can someone please explain what's the mistake is?
Regards
Alex
Change the function to:
HEADER *createHeader(void)
{
HEADER *yourHeader = malloc(sizeof(HEADER));
if (yourHeader == NULL)
printErrorAndExit();
yourHeader->first = NULL;
yourHeader->last = NULL;
yourHeader->length = 0;
return yourHeader;
}
Use:
Header *header = createHeader();
if (header == NULL)
exit(-1);
Alternatively, use a pointer to a pointer as the argument:
void createHeader(HEADER **yourHeader)
{
*yourHeader = malloc(sizeof(HEADER));
if (*yourHeader == NULL)
printError();
(*yourHeader)->first = NULL;
(*yourHeader)->last = NULL;
(*yourHeader)->length = 0;
}
Use:
Header *header = NULL;
createHeader(&header);
if (header == NULL)
exit(EXIT_FAILURE);
These two techniques can be applied to most 'allocate pointer' operations — creating linked lists is a particularly common variation. Note that fopen() and fclose() match the first model; the allocator (fopen()) takes some arguments to tell it what to do and the function returns a pointer to a structure that can be used and eventually passed to fclose() for release.
Note that printErrorAndExit() must not return. Or, if it does, the functions have to be revised:
HEADER *createHeader(void)
{
HEADER *yourHeader = malloc(sizeof(HEADER));
if (yourHeader == NULL)
printError();
else
{
yourHeader->first = NULL;
yourHeader->last = NULL;
yourHeader->length = 0;
}
return yourHeader;
}
It might be better for the function not to print any error message — that limits its reusability, in general.
HEADER *createHeader(void)
{
HEADER *yourHeader = malloc(sizeof(HEADER));
if (yourHeader != NULL)
{
yourHeader->first = NULL;
yourHeader->last = NULL;
yourHeader->length = 0;
}
return yourHeader;
}
The alternative design should probably return a status instead of nothing, so you can test the function result directly:
int createHeader(HEADER **yourHeader)
{
int rc = 0;
*yourHeader = malloc(sizeof(HEADER));
if (*yourHeader == NULL)
rc = -1; /* Or perhaps errno */
else
{
(*yourHeader)->first = NULL;
(*yourHeader)->last = NULL;
(*yourHeader)->length = 0;
}
return rc;
}
Use:
if (createHeader(&header) != 0)
…report error and bail out…
Using 0 for success and non-zero for failure is very common (many Unix system calls fall into this category). Very often, a negative return value indicates failure, especially if a positive value can be used for success — think open(). But the POSIX pthread functions frequently return a positive error number on failure and zero on success.
Related
I am using stm32f4 microproccessor and lwip library for the some ethernet process.
I have a problem with dynamic memory allocation. For some reason when I send ping to my hardware, this device experience Hardfault problem after 1 hour.
These are my firmware routine in main.c
while(1)
{
uint8_t * incomingData = ethernetif_input(&gnetif);
if(incomingData != NULL)
{
if(incomingData[0] == 0x01)
{
// doing some process
}
incomingData = NULL;
free(incomingData)
}
}
in ethernetif.c :
uint8_t * ethernetif_input(struct netif *netif)
{
struct pbuf *p;
p = low_level_input(netif);
if (p == NULL) {
return NULL;
}
uint8_t * data = (uint8_t*)(malloc(sizeof( uint8_t) * 61U));
if ((memcmp (p->payload, EXPECTED_ETHERNET_FRAME, 6) == 0))
{
for(int i = 0; i < 61; i++)
{
data[i]=(((uint8_t*)p->payload)[i]);
}
}
else
{
err = netif->input(p, netif);
data = NULL;
free(data);
if (err != ERR_OK)
{
pbuf_free(p);
p = NULL;
}
{
if(p != NULL)
{
pbufFreeErr = pbuf_free(p);
if( !(_Bool)pbufFreeErr)
{
}
}
return data;
}
You're running out of memory.
As already mentioned in the comments: data=NULL; free(data) does not make sense. It says forget what data pointed to and then do nothing with it.
You should first free(data)before setting it to NULL. That will make the memory pointed to by data available to future malloccalls.
And you should also call pbuf_free in all cases, you will run out of memory if you don't.
As a final remark, do not use a for loop to copy the buffer, use memcpy.
I want to know when I need to free a pointer that is returned from EFI functions
EFI_DEVICE_PATH_PROTOCOL *
BmExpandFileDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
)
{
EFI_STATUS Status;
UINTN Index;
UINTN HandleCount;
EFI_HANDLE *Handles;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
UINTN MediaType;
EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
BOOLEAN GetNext;
EfiBootManagerConnectAll ();
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);
if (EFI_ERROR (Status)) {
HandleCount = 0;
Handles = NULL;
}
GetNext = (BOOLEAN)(FullPath == NULL);
NextFullPath = NULL;
//
// Enumerate all removable media devices followed by all fixed media devices,
// followed by media devices which don't layer on block io.
//
for (MediaType = 0; MediaType < 3; MediaType++) {
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (Handles[Index], &gEfiBlockIoProtocolGuid, (VOID *) &BlockIo);
if (EFI_ERROR (Status)) {
BlockIo = NULL;
}
if ((MediaType == 0 && BlockIo != NULL && BlockIo->Media->RemovableMedia) ||
(MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||
(MediaType == 2 && BlockIo == NULL)
) {
NextFullPath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);
if (GetNext) {
break;
} else {
GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
FreePool (NextFullPath);
NextFullPath = NULL;
}
}
}
if (NextFullPath != NULL) {
break;
}
}
if (Handles != NULL) {
FreePool (Handles);
}
return NextFullPath;
}
for example, In this code, can I free Handles after calling HandleProtocol and still be able to use BlockIo?
Is there a document that explains the "pointer passing convention" of edk2 functions?
Thanks.
You have to look into the specification, if you are responsible to free the pointer there is a note.
For your LocateHandleBuffer example:
Buffer
A pointer to the buffer to return the requested array of handles that
support Protocol. This buffer is allocated with a call to the Boot
Service EFI_BOOT_SERVICES.AllocatePool(). It is the caller's
responsibility to call the Boot Service EFI_BOOT_SERVICES.FreePool()
when the caller no longer requires the contents of Buffer."
You can use the BlockIO protocols after you free the buffer, you are not freeing the handle instances (which would be a very bad idea), instead you are freeing an array of them.
I'm currently trying to compile a crc calculator I took from github and am having difficulty compiling it on visual studio 2015. I get the error expected constant expression for the line:
char paths[strlen(src) + 1 + strlen(name) + 2 + 1];
Thoughts on how I can resolve the error?
static int create_source(char *src, char *name, FILE **head, FILE **code) {
// for error return
*head = NULL;
*code = NULL;
// create the src directory if it does not exist
int ret = _mkdir(src, 0755);
if (ret && errno != EEXIST)
return 1;
// construct the path for the source files, leaving suff pointing to the
// position for the 'h' or 'c'.
char paths[strlen(src) + 1 + strlen(name) + 2 + 1];
char *suff = stpcpy(path, src);
*suff++ = '/';
suff = stpcpy(suff, name);
*suff++ = '.';
suff[1] = 0;
// create header file
*suff = 'h';
*head = fopen(path, "wx");
if (*head == NULL)
return errno == EEXIST ? 2 : 1;
// create code file
*suff = 'c';
*code = fopen(path, "wx");
if (*code == NULL) {
int err = errno;
fclose(*head);
*head = NULL;
*suff = 'h';
unlink(path);
return err == EEXIST ? 2 : 1;
}
// all good -- return handles for header and code
return 0;
}
Your immediate problem is you are attempting to use a VLA (Variable Length Array), introduced into the standard with C99, with a compiler that does not support VLAs. Without VLA support, arrays must be declared with an integer constant (not simply a const int). As of C11, support for VLAs is optional.
To solve your immediate problem and provide portability, simply allocate storage for paths instead with malloc. The free the memory before you return from your function (either though an error return or on success)
You can do something like:
size_t pathlen = strlen(src) + 1 + strlen(name) + 2 + 1;
char *paths = malloc (pathlen); /* allocate storage for paths */
if (!paths) { /* validate EVERY allocation */
perror ("malloc-paths");
return 3; /* or however you want to handle the error */
}
char *suff = stpcpy(path, src);
...
*head = fopen(path, "wx");
if (*head == NULL) {
free (path); /* free paths */
return errno == EEXIST ? 2 : 1;
}
...
if (*code == NULL) {
int err = errno;
free (path); /* free paths */
fclose(*head);
*head = NULL;
*suff = 'h';
unlink(path);
return err == EEXIST ? 2 : 1;
}
free (path); /* free paths */
return 0;
There is a small overhead for the allocation and free, but it is negligible in your case where there is a single allocation and single free.
As a simple alternative to David's solution, you could also use FILENAME_MAX ...
[...] which expands to an integer constant expression that is the size needed for an array of char large enough to hold the longest file name string that the implementation guarantees can be opened; (§7.21.1, ISO C11)
like this
char paths[FILENAME_MAX];
You might like to check that you don't overflow this size, though.
My program crached on Eclipse when i try to free my object - PokemonTrainer.I have tried the solution in this article, but it didn't help.
PokemonTrainer pokemonTrainerCreate(char* name, Pokemon initial_pokemon,
int max_num_local, int max_num_remote)
{
PokemonTrainer trainer = malloc(sizeof(PokemonTrainer));
if ((name == NULL) || (initial_pokemon == NULL) || (trainer == NULL) ||
(max_num_local < 0) || (max_num_remote < 0))
return NULL;
char tmp_name[strlen(name)];
strcpy(tmp_name, name);
trainer->name = tmp_name;
trainer->max_num_local = max_num_local;
trainer->max_num_remote = max_num_remote;
trainer->pokemons_local = malloc(sizeof(Pokemon)
trainer->max_num_local);
trainer->pokemons_remote = malloc(sizeof(Pokemon)
trainer->max_num_remote);
if (trainer->pokemons_remote == NULL) {
free(trainer->pokemons_local);
return NULL;
} else if (trainer->pokemons_local == NULL) {
free(trainer->pokemons_remote);
return NULL;
}
trainer->pokemons_local[0] = pokemonCopy(initial_pokemon);
trainer->curr_num_local = 1;
trainer->curr_num_remote = 0;
return trainer;
}
void pokemonTrainerDestroy(PokemonTrainer trainer)
{
if (trainer == NULL)
return;
if (trainer->curr_num_local > 0)
for (int i = trainer->curr_num_local - 1; i >= 0; i--)
pokemonDestroy(trainer->pokemons_local[i]);
if (trainer->curr_num_remote > 0)
for (int i = trainer->curr_num_remote - 1; i >= 0; i--)
pokemonDestroy(trainer->pokemons_remote[i]);
free (trainer); // here it's crashed
}
It is during the execution of free() in the stack that I am getting a "No source available for "ntdll!RtlpNtEnumerateSubKey() at 0x77cf04e5" error.
PokemonTrainer trainer = malloc(sizeof(PokemonTrainer)); is unlikely to work properly since you're allocating the size of the pointer, not the real data.
You won't have enough storage => undefined behaviour happens, and for you it happens when freeing the memory (corrupt memory list)
I would do this:
PokemonTrainer trainer = malloc(sizeof(*PokemonTrainer));
so the sizeof takes the size of the structure pointed by PokemonTrainer.
EDIT: for completeness, BLUEPIXY suggests that you've missing 1 byte here (because of null-termination char):
char tmp_name[strlen(name)];
strcpy(tmp_name, name);
and moreover this allocated space is temporary, so I'd suggest:
char *tmp_name = strdup(name);
which will allocate the correct size and performs a dynamic allocation that stays valid even after returning from the routine.
I'm writing a service in Linux using c, so I need to keep the memory usage stable.
But after tracing a day, the memory raise.
If I monitor from the System Monitor in Linux, it raise 1M and the mem%(0 -> 0.1).
In pmap command, it raise 1M, too.
I have use valgrind to check if there are any memory leak, and it report none if I run once.
If I start the service and use valgrind, it will report that I free invalid pointer.
So, I think it should have something to do about my pointer.
struct list {
int no;
BYTE parm[SLEN];
struct list *next;
};
struct list *memory_current;
struct list *memory_head;
struct list *memory_prev;
int getMemoryUsage(int sendCmd) {
pthread_mutex_lock(&lock);
FILE *fp = NULL;
BYTE buffer[10] = "";
BYTE memorys[10] = "";
int flag = 0;
TRY {
if ((fp = popen("free_data=$(free -m | grep Mem);total=$(echo $free_data | cut -f2 -d' ');"
"free_data=$(free -m | grep 'buffers/cache');buffers=$(echo $free_data | cut -f3 -d' ');echo $(($buffers*100/$total))", "r")) == NULL) {
THROW(CMD_NOT_FND);
}
else {
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
strcat(memorys, buffer);
memory_current = (struct list *)malloc(sizeof(struct list));
if (memory_current == NULL) {
THROW(MALLOC_ERROR);
}
memory_current->next = NULL;
strncpy(memory_current->parm, buffer, SLEN -1);
memory_current->parm[SLEN -1] = '\0';
if (memory_head == NULL)
memory_head = memory_current;
else
memory_prev->next = memory_current;
memory_prev = memory_current;
memset(buffer, 0, sizeof(buffer));
flag = 1;
}
if (flag == 0)
THROW(CMD_NOT_FND);
}
}
CATCH (CMD_NOT_FND) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage % : %s\n", memorys);
printLog("Memory Usage % ->", memorys);
}
CATCH (MALLOC_ERROR) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage malloc error : %s\n", memorys);
printLog("Memory Usage malloc error ->", memorys);
}
FINALLY {
pclose(fp);
// printf("Memory Usage % : %s\n", memorys);
// printf("Memory Usage length %d\n", strlen(memorys));
}
ETRY;
if (sendCmd == 1) {
if (flag != 0) {
memory_current = memory_head;
int totalMemory = 0;
int count = 0;
int avg = 0;
int perc = 0;
BYTE avg_memory[10] = "";
while (memory_current != NULL) {
sscanf(memory_current->parm, "%d", &perc);
totalMemory += perc;
memory_current = memory_current->next;
count++;
}
avg = totalMemory / count;
snprintf(avg_memory, sizeof(avg_memory), "%d", avg); ;
strcat(avg_memory, ";");
printf("Memory Usage % : %s\n", avg_memory);
printLog("Memory Usage % ->", avg_memory);
// free linked list
memory_current = memory_head;
while (memory_current != NULL) {
memory_prev = memory_current;
memory_current = memory_current->next;
free(memory_prev);
memory_prev = NULL; //fix dangling
}
head_memory = NULL; //fix dangling
current_memory = NULL; //fix dangling
}
}
pthread_mutex_unlock(&lock);
return 0;
}
I have the global pointer to keep record the memory usage in a timer, and I will use the result and clear the list in a interval of time.
I use the same way to use in other function and the memory usage is fine, but the pointers are local and will free at the end.
Could you please help to advice or pointer out what is wrong about my pointer usage.
Thanks.
[Update]
I found that this might be a dangling pointer, so I set the pointer to NULL after the free.
So far the memory won't raise, but I'll keep watching it for more days.
Solved
The memory won't raise again, so I guess it's the dangling pointer issue.
memory_current, memory_head and memory_prev were not initialized to NULL.
you check:
if (memory_head == NULL)
when memory_head was not initialized, therefore you maybe loose some memory allocations
also look like they should be local variables, not global.