Need an example of using mmem in Contiki - c

I am developing code to use in the COOJA simulator. I used malloc() for all of the dynamic memory allocations. While the simulation is running, COOJA motes restart periodically and at last I get an error which tells me the reason is I'm using malloc().
I'm thinking of using Contiki's specific memory allocation class named "mmem". I could not found any example of using it. Here is an example in which I used malloc() to allocate memory to a string named sent.
How do I replace using malloc() to use mmem instead of malloc()?
char *sent;
sent = (char*)malloc(120);
strncpy(sent , "example" , 7);
strncat(sent , "|", 1);

From Contiki’s github Wiki
Here is an example of how to use the managed memory allocator:
#include "contiki.h"
#include "lib/mmem.h"
static struct mmem mmem;
static void
test_mmem(void)
{
struct my_struct {
int a;
} my_data, *my_data_ptr;
if(mmem_alloc(&mmem, sizeof(my_data)) == 0) {
printf("memory allocation failed\n");
} else {
printf("memory allocation succeeded\n");
my_data.a = 0xaa;
memcpy(MMEM_PTR(&mmem), &my_data, sizeof(my_data));
/* The cast below is safe only if the struct is packed */
my_data_ptr = (struct my_struct *)MMEM_PTR(&mmem);
printf("Value a equals 0x%x\n", my_data_ptr->a);
mmem_free(&mmem);
}
}
The example above shows a basic example of how the managed memory
library can be used. On line 4, we allocate a variable, mmem, that
identifies the managed memory object that we are about to allocate. On
line 13, we use the mmem variable as an argument for mmem_alloc() to
allocate space for a structure of sizeof(my_data) bytes. If the
allocation succeeded, we copy the values from an existing structure
into the allocated structure, pointed to by MMEM_PTR(&mmem).
Individual members of allocated structure can then be accessed by a
type cast of MMEM_PTR(&mmem) to struct my_struct *, as shown on line
20. Note that the cast is only safe if the struct is packed. The managed memory is finally deallocated on line 21 by calling
mmem_free().
.
EDIT:
From the code you've pasted in the comments, there is no need to use malloc or the mmem-module. Just allocate on the stack. Maybe try something like this instead:
/* Allocate memory on the stack */
char sent[120];
/* Manipulate strings */
strncpy(sent , "reqid" , 5);
strncat(sent, "|", 1);
/* Send UDP packet */
uip_udp_packet_send(mcast_conn, sent, strlen(sent));
/* Print out string sent */
printf(" (msg: %s)\n", sent);
EDIT 2:
Here is a page on heap vs stack. and here is a stackoverflow question about dynamic allocation on embedded devices and the problems it involves.

Related

is this the proper way to initialize a pointer to struct? thank you

how to create a pointer to struct the proper way?
typedef struct account{
char name[80];
int acct_year;
}account;
int main
{
account *accountant;// is this the proper way?
}
I wrote comments in the code to explain things.
Let me know if still confusing.
#include <stdio.h>
// This is needed for strncpy
#include <string.h>
// This is needed for malloc
#include <stdlib.h>
struct Account {
char name[80];
int acct_year;
};
int main()
{
// Normal declaration of a variable of type Account
struct Account userAccount;
// Using strncpy is safer than using strcpy. Read about overflow buffer attack.
char* userName = "Alex";
strncpy(userAccount.name, userName, sizeof(userName));
userAccount.acct_year = 4;
printf("User Account: %s %d\n", userAccount.name, userAccount.acct_year);
// Creating a pointer to access the struct we declare and initiate above;
struct Account *pUserAccount;
// Pass the address of the variable above inside the pointer
pUserAccount = &userAccount;
// We can replace the value in userAccount from the pointer
pUserAccount->acct_year = 5;
// Compare to see that we changed the value in userAccount using the pointer
printf("Pointer User Account: %s %d\n", pUserAccount->name, pUserAccount->acct_year);
printf("User Account: %s %d\n", userAccount.name, userAccount.acct_year);
// Let's create a pointer and give it some space from the Heap memory
struct Account *pAdminAccount;
pAdminAccount = malloc(sizeof (struct Account));
// We always check because we could have run out of memory or something failed
if (pAdminAccount != NULL) {
// Due my lazyness, I am copying the name from userAccount inside pAdminAccount
strncpy(pAdminAccount->name, userAccount.name, sizeof(userAccount.name));
pAdminAccount->acct_year = 6;
printf("Pointer Heap Adminr Account: %s %d\n", pAdminAccount->name, pAdminAccount->acct_year);
// Always free the memory when you are not using it.
free(pAdminAccount);
}
return 0;
}
Note: I haven't done C in ages so double check what I am explaining here.
Explanation:
So, there are different ways that you can use a struct.
The first way to use is is like any other type such as int, char, bool, etc.
If I do int a; a = 4;, memory from the stack is provided that will be available inside the block it has being declared. So, if you create it inside a function, it will be available until you exit the function, even if you return the address of such variable using &. Don't do it.
So, struct Account userAccount; will create a variable that you can right away use it: userAccount.acct_year = 4;
If you wish to access indirectly using a pointer, then you need to create a pointer struct Account *pUserAccount;. In this pointer, is where we save the address of userAccount in this way: pUserAccount = &userAccount. Notices that I didn't use the * since we are not accessing.
The advantage of using this method is that the compiler knows the size of what we are pointing at. Later, when you are familiar with this, you can play with an array of structs and how to access them using pointers.
Anyways, continue with the explanation.
If you wish for example to have a function that creates an account and using such account outside a function, then you must use malloc. malloc fetch memory from the Heap and return an address to such memory location.
You must tell malloc how much memory you wish to reserve: sizeof (struct Account).
As explained, malloc(sizeof (struct Account)); will return an address.
Now, you can return that address from your function or use it right away.
Its important that you check for NULL since malloc might fail to get reserve memory (i.e. out of memory).
Also, its important for you to clean up after yourself. Free the memory you have taken in the Heap so other programs can use it too. This will prevent many issues such as memory segmentation and such.
You can declare it as struct Account userAccount; and automatically memory will be allocated in the whole life of the block. If the declaration of the
You have two options on how you Initialize a declared pointer. Take your example:
typedef struct account {
char name[80];
int acct_year;
} account;
int main (void)
{
account *accountant;
}
Above, accountant is an Uninitialized pointer that holds an indeterminate (could be anything) address as its value. To initialize the pointer, you must either (1) assign the address of an existing type account to it, e.g.
int main (void)
{
account account1 = { "Client A", 2019 }; /* object of type account */
account *accountant = &account1; /* address assigned to pointer */
/* use accountant as needed */
printf ("\naccountant: %s (%d)\n", accountant->name, accountant->acct_year);
}
Or, (2) dynamically allocate storage for accountant with malloc, calloc or realloc, e.g.
int main (void)
{
account *accountant = malloc (sizeof *accountant); /* allocate for 1 account */
if (accountant == NULL) { /* validate every allocation */
perror ("malloc-accountant");
return 1;
}
strcpy (accountant->name, "Client A");
accountant->acct_year = 2019;
/* use accountant as needed */
printf ("\naccountant: %s (%d)\n", accountant->name, accountant->acct_year);
free (accountant); /* free what you allocate */
}
Either way is fine. A pointer is simply a normal variable that holds the address where something else is stored in memory as its value. In other words, a pointer points to the address where something else can be found. You have to make sure that address the pointer holds as its value points to a valid memory address holding an object of that type. If you always ask "Where does my pointer point?" before using it -- you will never have trouble with pointers again.
The usual way is to use the malloc() system call to allocate a block of memory
big nough for your structure type onto the system heap. You will want to check
that actually happened in case you are out of memory.
account * accountant;
if ((accountant = malloc ( sizeof(struct account))) == NULL)
{
errno = ENOMEM;
return some error token.
}
...continue knowing the pointer has been initialised.
When you are finished MAKE SURE you free the block back to the system with
free (accountant);

Difference between vm_offset_t, (void *), and mach_vm_size_t

I'm trying to understand this code for reading virtual memory mappings but I'm having trouble understanding the different data types as I can't find any good documentation.
What is the difference between vm_offset_t, void *, and mach_vm_size_t? On my machine they all seem to be 8 bytes (64-bit) and used to navigate virtual memory. What are the differences between their purposes? What is the point of having these different types?
EDIT:
For instance, in the linked code:
unsigned char *
readProcessMemory (int pid, mach_vm_address_t addr, mach_msg_type_number_t *size)
{
// Helper function to read process memory (a la Win32 API of same name)
// To make it easier for inclusion elsewhere, it takes a pid, and
// does the task_for_pid by itself. Given that iOS invalidates task ports
// after use, it's actually a good idea, since we'd need to reget anyway
task_t t;
task_for_pid(mach_task_self(),pid, &t);
mach_msg_type_number_t dataCnt = size;
vm_offset_t readMem;
// Use vm_read, rather than mach_vm_read, since the latter is different
// in iOS.
kern_return_t kr = vm_read(t, // vm_map_t target_task,
addr, // mach_vm_address_t address,
*size, // mach_vm_size_t size
&readMem, //vm_offset_t *data,
size); // mach_msg_type_number_t *dataCnt
if (kr) {
// DANG..
fprintf (stderr, "Unable to read target task's memory #%p - kr 0x%x\n" , addr, kr);
return NULL;
}
return ( (unsigned char *) readMem);
}
According to this documentation of the vm_read function, the data_out parameter is an "Out-pointer to dynamic array of bytes returned by the read."
But in the code above they pass in &readMem (which is type vm_offset_t *) for data_out. I'm confused how `readMem is being used here - is it a pointer to the dynamic array of bytes returned by the read? Or does it actually contain the dynamic array of bytes? Is vm_offset_t a pointer or an address? What is its purpose?
Similarly
vm_offset_t, void*, and mach_vm_size_t are all internally synonymous with unsigned long, but they are used to make the code more readable and expressive.
vm_read returns an address in readMem, meaning that readMem will need to be cast to a pointer and dereferenced to access its value.
Also, the memory region pointed to by readMem is allocated by the kernel, so it needs to be deallocated with vm_deallocate. To avoid this, consider using vm_read_overwrite which will populate the buffer it is supplied.

Freeing malloced structure in a function

I'm creating a source files containing buffer functionality that I want to use for my other library that I'm creating.
It is working correctly but I'm having trouble getting rid of the buffer structure that I'm creating in one of the functions. The following snippets should help illustrate my problem:
C header:
//dbuffer.h
...
typedef struct{
char *pStorage;
int *pPosition;
int next_position;
int number_of_strings;
int total_size;
}DBUFF;
...
C source:
//dbuffer.c
...
DBUFF* dbuffer_init(char *init_pArray)
{
//Find out how many elements the array contains
int size = sizeof_pArray(init_pArray);
//Initialize buffer structure
DBUFF *buffer = malloc(sizeof(DBUFF));
//Initialize the storage
buffer->pStorage = malloc( (sizeof(char)) * (size) );
strncpy( &(buffer->pStorage)[0] , &init_pArray[0] , size);
buffer->number_of_strings = 1;
buffer->total_size = size;
buffer->next_position = size; //size is the next position because array allocates elements from 0 to (size-1)
//Initialize the position tracker which keeps record of starting position for each string
buffer->pPosition = malloc(sizeof(int) * buffer->number_of_strings );
*(buffer->pPosition + (buffer->number_of_strings -1) ) = 0;
return buffer;
}
void dbuffer_destroy(DBUFF *buffer)
{
free(buffer->pStorage);
free(buffer);
}
...
Main:
#include <stdio.h>
#include <stdlib.h>
#include "dbuffer.h"
int main(int argc, char** argv)
{
DBUFF *buff;
buff = dbuffer_init("Bring the action");
dbuffer_add(buff, "Bring the apostles");
printf("BUFFER CONTENTS: ");
dbuffer_print(buff);
dbuffer_destroy(buff);
// Looks like it has been succesfully freed because output is garbage
printf("%s\n", buff->pStorage);
//Why am I still able to access struct contents after the pointer has been freed ?
printf("buff total size: %d\n", buff->total_size);
return (EXIT_SUCCESS);
}
Output:
BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36
RUN SUCCESSFUL (total time: 94ms)
Question:
Why am I still able to access struct contents using the line below after the pointer to the struct has been freed ?
printf("buff total size: %d\n", buff->total_size);
Once you've called free() on the allocated pointer, attempt to make use of the pointer invokes undefined behavior. You should not be doing that.
To quote C11 standard, chapter §7.22.3.4, free() function
The free() function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. [..]
It never say's anything about a cleanup, which you might be (wrongly) expecting.
Just to add clarity, calling free() does not always actually free up the allocated physical memory. It just enables that pointer (memory space) to be allocated again (returning the same pointer, for example) for successive calls to malloc() and family. After calling free(), that pointer is not supposed to be used from your program anymore but C standard does not guarantee of a cleanup of the allocated memory.
If any attempt is made to read memory that has been freed can crash your program. Or they might not. As far as the language is concerned, its undefined behaviour.
Your compiler won't warn you about it(or stop you from accessing it). But clearly don't do this after calling free -
printf("buff total size: %d\n", buff->total_size);
As a good practice you can set the freed pointer to NULL .
free() call will just mark the memory in heap as available for use. So you still have the pointer pointing to this memory location but it's not available anymore for you. Thus, the next call to malloc() is likely to assign this memory to the new reservation.
To void this situations normally once you free() the memory allocated to a pointer you should set it to NULL. De-referencing NULL is UB also but at least when debugging you can see tha pointer should not be used because it's not pointing to a valid memory address.
[too long for a comment]
To allow your "destructor" to set the pointer passed to NULL modify your code like this:
void dbuffer_destroy(DBUFF ** buffer)
{
if ((NULL == buffer) || (NULL == *buffer))
{
return;
}
free((*buffer)->pPosition);
free((*buffer)->pStorage);
free(*buffer);
*buffer = NULL;
}
and call it like this:
...
dbuffer_destroy(&buff);
...

How can I initialize an empty Buffer in C language

I'm doing a work in wish I have to read caracters from a File, and save them in a buffer. Later i have to output them, but for know I'm still struggling with the buffer thing.
I would like to know how can I initialize the buffer(empty of course) and then put caracters into that buffer.
I want to do it in another function who is called by int main(..).Here's waht I have:
buffer_t initBuffer(void) {
// Reserves space for the buffer, ends program if it cant reserve space.
buffer_t buffer = malloc(sizeof(*buffer));
if (buffer == NULL) {
printf("Error allocating bufefr\n");
exit(1);
}
after this, how can I initialize it with his counter at 0?
Definition of buffer_t:
typedef struct buffer_s *buffer_t;
struct buffer_s {
unsigned char buffer[BUF_SIZE];
counter;
}
There are two apprroaches for two different needs. Choose whichever suits your requirement.
If you want to initialize your allocated memory area to 0, you can use calloc() to directly do that (allocate and initialize to 0).
If you want to initialize your allocated buffer to some other value, you can use memset() after doing a malloc().

Checking if a pointer is allocated memory or not

Can we check whether a pointer passed to a function is allocated with memory or not in C?
I have wriiten my own function in C which accepts a character pointer - buf [pointer to a buffer] and size - buf_siz [buffer size]. Actually before calling this function user has to create a buffer and allocate it memory of buf_siz.
Since there is a chance that user might forget to do memory allocation and simply pass the pointer to my function I want to check this. So is there any way I can check in my function to see if the pointer passed is really allocated with buf_siz amount of memory .. ??
EDIT1: It seems there is no standard library to check it .. but is there any dirty hack to check it .. ??
EDIT2: I do know that my function will be used by a good C programmer ... But I want to know whether can we check or not .. if we can I would like to hear to it ..
Conclusion: So it is impossible to check if a particular pointer is allocated with memory or not within a function
You cannot check, except some implementation specific hacks.
Pointers have no information with them other than where they point. The best you can do is say "I know how this particular compiler version allocates memory, so I'll dereference memory, move the pointer back 4 bytes, check the size, makes sure it matches..." and so on. You cannot do it in a standard fashion, since memory allocation is implementation defined. Not to mention they might have not dynamically allocated it at all.
You just have to assume your client knows how to program in C. The only un-solution I can think of would be to allocate the memory yourself and return it, but that's hardly a small change. (It's a larger design change.)
The below code is what I have used once to check if some pointer tries to access illegal memory. The mechanism is to induce a SIGSEGV. The SEGV signal was redirected to a private function earlier, which uses longjmp to get back to the program. It is kind of a hack but it works.
The code can be improved (use 'sigaction' instead of 'signal' etc), but it is just to give an idea. Also it is portable to other Unix versions, for Windows I am not sure. Note that the SIGSEGV signal should not be used somewhere else in your program.
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <signal.h>
jmp_buf jump;
void segv (int sig)
{
longjmp (jump, 1);
}
int memcheck (void *x)
{
volatile char c;
int illegal = 0;
signal (SIGSEGV, segv);
if (!setjmp (jump))
c = *(char *) (x);
else
illegal = 1;
signal (SIGSEGV, SIG_DFL);
return (illegal);
}
int main (int argc, char *argv[])
{
int *i, *j;
i = malloc (1);
if (memcheck (i))
printf ("i points to illegal memory\n");
if (memcheck (j))
printf ("j points to illegal memory\n");
free (i);
return (0);
}
For a platform-specific solution, you may be interested in the Win32 function IsBadReadPtr (and others like it). This function will be able to (almost) predict whether you will get a segmentation fault when reading from a particular chunk of memory.
However, this does not protect you in the general case, because the operating system knows nothing of the C runtime heap manager, and if a caller passes in a buffer that isn't as large as you expect, then the rest of the heap block will continue to be readable from an OS perspective.
I always initialize pointers to null value. Therefore when I allocate memory it will change. When I check if memory's been allocated I do pointer != NULL. When I deallocate memory I also set pointer to null. I can't think of any way to tell if there was enough memory allocated.
This doesn't solve your problem, but you got to trust that if someone writes C programs then he is skilled enough to do it right.
I once used a dirty hack on my 64bit Solaris. In 64bit mode the heap starts at 0x1 0000 0000. By comparing the pointer I could determine if it was a pointer in the data or code segment p < (void*)0x100000000, a pointer in the heap p > (void*)0x100000000 or a pointer in a memory mapped region (intptr_t)p < 0 (mmap returns addresses from the top of the addressable area).
This allowed in my program to hold allocated and memory mapped pointers in the same map, and have my map module free the correct pointers.
But this kind of trick is highly unportable and if your code relies on something like that, it is time to rethink the architecture of your code. You're probably doing something wrong.
I know this is an old question, but almost anything is possible in C. There are a few hackish solutions here already, but a valid way of determining if memory has been properly allocated is to use an oracle to take the place of malloc, calloc, realloc, and free. This is the same way testing frameworks (such as cmocka) can detect memory problems (seg faults, not freeing memory, etc.). You can maintain a list of memory addresses allocated as they are allocated and simply check this list when the user wants to use your function. I implemented something very similar for my own testing framework. Some example code:
typedef struct memory_ref {
void *ptr;
int bytes;
memory_ref *next;
}
memory_ref *HEAD = NULL;
void *__wrap_malloc(size_t bytes) {
if(HEAD == NULL) {
HEAD = __real_malloc(sizeof(memory_ref));
}
void *tmpPtr = __real_malloc(bytes);
memory_ref *previousRef = HEAD;
memory_ref *currentRef = HEAD->next;
while(current != NULL) {
previousRef = currentRef;
currentRef = currentRef->next;
}
memory_ref *newRef = (memory_ref *)__real_malloc(sizeof(memory_ref));
*newRef = (memory_ref){
.ptr = tmpPtr,
.bytes = bytes,
.next = NULL
};
previousRef->next = newRef;
return tmpPtr;
}
You would have similar functions for calloc, realloc, and free, each wrapper prefixed with __wrap_. The real malloc is available through the use of __real_malloc (similar for the other functions you are wrapping). Whenever you want to check if memory is actually allocated, simply iterate over the linked memory_ref list and look for the memory address. If you find it and it's big enough, you know for certain the memory address won't crash your program; otherwise, return an error. In the header file your program uses, you would add these lines:
extern void *__real_malloc (size_t);
extern void *__wrap_malloc (size_t);
extern void *__real_realloc (size_t);
extern void *__wrap_realloc (size_t);
// Declare all the other functions that will be wrapped...
My needs were fairly simple so I implemented a very basic implementation, but you can imagine how this could be extended to have a better tracking system (e.g. create a struct that keeps track of the memory location in addition to the size). Then you simply compile the code with
gcc src_files -o dest_file -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,free
The disadvantage is the user has to compile their source code with the above directives; however, it's far from the worse I have seen. There is some overhead to allocating and freeing memory, but there is always some overhead when adding security.
No, in general there is no way to do this.
Furthermore, if your interface is just "pass a pointer to a buffer where I will put stuff", then the caller may choose not to allocate memory at all, and instead use a fixed size buffer that's statically allocated or an automatic variable or something. Or perhaps it's a pointer into a portion of a larger object on the heap.
If your interface specifically says "pass a pointer to allocated memory (because I'm going to deallocate it)", then you should expect that the caller will do so. Failure to do so isn't something you can reliably detect.
One hack you can try is checking if your pointer points to stack allocated memory.
This will not help you in general as the allocated buffer might be to small or the pointer points to some global memory section (.bss, .const, ...).
To perform this hack, you first store the address of the first variable in main(). Later, you can compare this address with the address of a local variable in your specific routine.
All addresses between both addresses are located on the stack.
Well, I don't know if somebody didn't put it here already or if it will be a possibility in your programme. I was struggling with similar thing in my university project.
I solved it quite simply - In initialization part of main() , after I declared LIST *ptr, I just put that ptr=NULL. Like this -
int main(int argc, char **argv) {
LIST *ptr;
ptr=NULL;
So when allocation fails or your pointer isn't allocated at all, it will be NULL. SO you can simply test it with if.
if (ptr==NULL) {
"THE LIST DOESN'T EXIST"
} else {
"THE LIST MUST EXIST --> SO IT HAS BEEN ALLOCATED"
}
I don't know how your programme is written, but you surely understand what am I trying to point out. If it is possible to check like this your allocation and then pass your arguments to you function, you could have a simple solution.
Of course you must be careful to have your functions with allocating and creating the structure done well but where in C you don't have to be careful.
I don't know a way of doing it from a library call, but on Linux, you can look at /proc/<pid>/numa_maps. It will show all sections of memory and the third column will say "heap" or "stack". You can look at the raw pointer value to see where it lines up.
Example:
00400000 prefer:0 file=/usr/bin/bash mapped=163 mapmax=9 N0=3 N1=160
006dc000 prefer:0 file=/usr/bin/bash anon=1 dirty=1 N0=1
006dd000 prefer:0 file=/usr/bin/bash anon=9 dirty=9 N0=3 N1=6
006e6000 prefer:0 anon=6 dirty=6 N0=2 N1=4
01167000 prefer:0 heap anon=122 dirty=122 N0=25 N1=97
7f39904d2000 prefer:0 anon=1 dirty=1 N0=1
7f39904d3000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N0=1
7f39904d4000 prefer:0 file=/usr/lib64/ld-2.17.so anon=1 dirty=1 N1=1
7f39904d5000 prefer:0 anon=1 dirty=1 N0=1
7fffc2d6a000 prefer:0 stack anon=6 dirty=6 N0=3 N1=3
7fffc2dfe000 prefer:0
So pointers that are above 0x01167000 but below 0x7f39904d2000 are located in the heap.
You can't check with anything available in standard C. Even if your specific compiler were to provide a function to do so, it would still be a bad idea. Here's an example of why:
int YourFunc(char * buf, int buf_size);
char str[COUNT];
result = YourFunc(str, COUNT);
As everyone else said, there isn't a standard way to do it.
So far, no-one else has mentioned 'Writing Solid Code' by Steve Maguire. Although castigated in some quarters, the book has chapters on the subject of memory management, and discusses how, with care and complete control over all memory allocation in the program, you can do as you ask and determine whether a pointer you are given is a valid pointer to dynamically allocated memory. However, if you plan to use third party libraries, you will find that few of them allow you to change the memory allocation routines to your own, which greatly complicates such analysis.
in general lib users are responsible for input check and verification. You may see ASSERT or something in the lib code and they are used only for debug perpose. it is a standard way when writing C/C++. while so many coders like to do such check and verfying in their lib code very carefully. really "BAD" habits. As stated in IOP/IOD, lib interfaces should be the contracts and make clear what will the lib do and what will not, and what a lib user should do and what should be not necessary.
There is a simple way to do this. Whenever you create a pointer, write a wrapper around it. For example, if your programmer uses your library to create a structure.
struct struct_type struct_var;
make sure he allocates memory using your function such as
struct struct_type struct_var = init_struct_type()
if this struct_var contains memory that is dynamically allocated, for ex,
if the definition of struct_type was
typedef struct struct_type {
char *string;
}struct_type;
then in your init_struct_type() function, do this,
init_struct_type()
{
struct struct_type *temp = (struct struct_type*)malloc(sizeof(struct_type));
temp->string = NULL;
return temp;
}
This way,unless he allocates the temp->string to a value, it will remain NULL. You can check in the functions that use this structure, if the string is NULL or not.
One more thing, if the programmer is so bad, that he fails to use your functions, but rather directly accesses unallocated the memory, he doesn't deserve to use your library. Just ensure that your documentation specifies everything.
No, you can't. You'll notice that no functions in the standard library or anywhere else do this. That's because there's no standard way to tell. The calling code just has to accept responsibility for correctly managing the memory.
An uninitialised pointer is exactly that - uninitialised. It may point to anything or simply be an invalid address (i.e. one not mapped to physical or virtual memory).
A practical solution is to have a validity signature in the objects pointed to. Create a malloc() wrapper that allocates the requested block size plus the sizeof a signature structure, creates a signature structure at the start of the block but returns the pointer to the location after the signature. You can then create a validation function that takes the pointer, uses a negative offset to get the validity structure and checks it. You will of course need a corresponding free() wrapper to invalidate the block by overwriting the validity signature, and to perform the free from the true start of the allocated block.
As a validity structure, you might use the size of the block and its one's complement. That way you not only have a way of validating the block (XOR the two values and compare to zero), but you also have information about the block size.
A pointer tracker, tracks and checks the validity of a pointer
usage:
create memory int * ptr = malloc(sizeof(int) * 10);
add the pointer address to the tracker Ptr(&ptr);
check for failing pointers PtrCheck();
and free all trackers at the end of your code
PtrFree();
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
struct my_ptr_t { void ** ptr; size_t mem; struct my_ptr_t *next, *previous; };
static struct my_ptr_t * ptr = NULL;
void Ptr(void * p){
struct my_ptr_t * tmp = (struct my_ptr_t*) malloc(sizeof(struct my_ptr_t));
printf("\t\tcreating Ptr tracker:");
if(ptr){ ptr->next = tmp; }
tmp->previous = ptr;
ptr = tmp;
ptr->ptr = p;
ptr->mem = **(size_t**) ptr->ptr;
ptr->next = NULL;
printf("%I64x\n", ptr);
};
void PtrFree(void){
if(!ptr){ return; }
/* if ptr->previous == NULL */
if(!ptr->previous){
if(*ptr->ptr){
free(ptr->ptr);
ptr->ptr = NULL;
}
free(ptr);
ptr = NULL;
return;
}
struct my_ptr_t * tmp = ptr;
for(;tmp != NULL; tmp = tmp->previous ){
if(*tmp->ptr){
if(**(size_t**)tmp->ptr == tmp->mem){
free(*tmp->ptr);
*tmp->ptr = NULL;
}
}
free(tmp);
}
return;
};
void PtrCheck(void){
if(!ptr){ return; }
if(!ptr->previous){
if(*(size_t*)ptr->ptr){
if(*ptr->ptr){
if(**(size_t**) ptr->ptr != ptr->mem){
printf("\tpointer %I64x points not to a valid memory address", ptr->mem);
printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *ptr->ptr);
return;
}
}
return;
}
return;
}
struct my_ptr_t * tmp = ptr;
for(;tmp->previous != NULL; tmp = tmp->previous){
if(*(size_t*)tmp->ptr){
if(*tmp->ptr){
if(**(size_t**) tmp->ptr != tmp->mem){
printf("\tpointer %I64x points not to a valid memory address", tmp->mem);
printf(" did you freed the memory and not NULL'ed the pointer or used arthmetric's on pointer %I64x?\n", *tmp->ptr); continue;
}
}
continue;
}
}
return;
};
int main(void){
printf("\n\n\t *************** Test ******************** \n\n");
size_t i = 0;
printf("\t *************** create tracker ********************\n");
int * ptr = malloc(sizeof(int) * 10);
Ptr(&ptr);
printf("\t *************** check tracker ********************\n");
PtrCheck();
printf("\t *************** free pointer ********************\n");
free(ptr);
printf("\t *************** check tracker ********************\n");
PtrCheck();
printf("\t *************** set pointer NULL *******************\n");
ptr = NULL;
printf("\t *************** check tracker ********************\n");
PtrCheck();
printf("\t *************** free tracker ********************\n");
PtrFree();
printf("\n\n\t *************** single check done *********** \n\n");
printf("\n\n\t *************** start multiple test *********** \n");
int * ptrs[10];
printf("\t *************** create trackers ********************\n");
for(; i < 10; i++){
ptrs[i] = malloc(sizeof(int) * 10 * i);
Ptr(&ptrs[i]);
}
printf("\t *************** check trackers ********************\n");
PtrCheck();
printf("\t *************** free pointers but set not NULL *****\n");
for(i--; i > 0; i-- ){ free(ptrs[i]); }
printf("\t *************** check trackers ********************\n");
PtrCheck();
printf("\t *************** set pointers NULL *****************\n");
for(i=0; i < 10; i++){ ptrs[i] = NULL; }
printf("\t *************** check trackers ********************\n");
PtrCheck();
printf("\t *************** free trackers ********************\n");
PtrFree();
printf("\tdone");
return 0;
}
I'm not sure how fast msync is, but this is a linux only solution:
// Returns 1 if the ponter is mapped
int pointer_valid (void *p)
{
size_t pg_size = sysconf (_SC_PAGESIZE);
void *pg_start = (void *) ((((size_t)p) / pg_size) * pg_size);
return msync (pg_start, pg_size, MS_ASYNC) == 0;
}
There is almost never "never" in computers. Cross platform is way over anticipated. After 25 years I have worked on hundreds of projects all anticipating cross platform and it never materialized.
Obviously, a variable on the stack, would point to an area on the stack, which is almost linear. Cross platform garbage collectors work, by marking the top or (bottom) of the stack, calling a little function to check if the stack grows upwards or downwards and then checking the stack pointer to know how big the stack is. This is your range. I don't know a machine that doesn't implement a stack this way (either growing up or down.)
You simply check if the address of our object or pointer sits between the top and bottom of the stack. This is how you would know if it is a stack variable.
Too simple. Hey, is it correct c++? No. Is correct important? In 25 years I have seen way more estimation of correct. Well, let's put it this way: If you are hacking, you aren't doing real programming, you are probably just regurigating something that's already been done.
How interesting is that?

Resources