I'm working on a project and I have a list of functions to use.
I use the provided DLL.
I have the function's prototypes in the file "list.h".
This file is also provided to me
list.h
typedef unsigned short (__stdcall * ReadConfig)
(void * * pDataOut,
size_t * pSizeDataOut);
I wrote this main.c
int main (int nbArg, char** listeArg)
{
// Initialization
unsigned short outputFunction;
void * pointerMemoryZone = NULL;
size_t sizeMemoryZone = NULL;
// Load DLL
HMODULE dllLoadOuput= LoadLibrary("dllFile");
// Alias Creation
typedef unsigned short(*A_ReadConfig) (void * *, size_t *);
// Get Pointer on Function
A_ReadConfig ptrReadConfiguration = (A_ReadConfig)GetProcAddress(dllLoadOuput, "ReadConfig");
// Launch of the function
outputFunction = ptrReadConfiguration(&pointerMemoryZone, &sizeMemoryZone);
// Display
printf("\n\nSize Read Config : %ld\n\n", sizeMemoryZone);
// Unload DLL
FreeLibrary(dllLoadOuput);
return 0;
}
This program works and I get the size of the memory area fine.
But my program, my variables are they correctly declared and used...?
And how can I read the data contained in the memory area...?
Below is a diagram provided in the documentation :
Presumming outputFunction indicates success, the pointer pointerMemoryZone should contain sizeMemoryZone bytes of data.
How you access the data depends on the format (e.g. text/json/xml string).
A sample loop to display the data in ascii and hex:
for(int i=0; i<sizeMemoryZone; i++) {
char c = ((char*) pointerMemoryZone)[i];
printf("%c{%x} ", c, c);
}
I answer to my question. I find a solution.
I have to read datas byte by byte.
So I create a caracter pointer on "pointerMemoryZone" (wich contains adress of datas) by forcing the pointer type to character (because 1 byte)
And I make a loop in which I loop through the addresses one by one (along the length of the data)
Below the code for the loop
//...
//...
//...
// Launch of the function
outputFunction = ptrReadConfiguration(&pointerMemoryZone, &sizeMemoryZone);
// Creation of Pointer
char *pointerOnPointerMemoryZone = NULL;
// Begin Loop
for (int i = 0; i < sizeMemoryZone; i++)
{
// Association Pointer to Adress (+0, +1, +2, etc..)
pointerOnPointerMemoryZone = (char*)pointerMemoryZone + i;
printf("\n%d\t\t%d\t\t%c",i, *pointerOnPointerMemoryZone, *pointerOnPointerMemoryZone);
}
// End Loop
//...
//...
//...
Related
I am working on a series of C functions to allow a user to dynamically build an array. The core of the library resides in the Array struct which contains a pointer variable array that contains the array data, len which contains the length of the array, size, which is the total memory allocation for the array, elem, which contains the memory allocation per indices, and pointer variables name and dtype which contains strings describing the name of the array and the type of the array. For the moment I have constrained the scope so that only int, float, double, and char arrays can be considered.
Thus far I have defined, and individually tested the following functions;
array_mem_alloc which contains code that allocates memory for an array.
init_array which is a wrapper around array_mem_alloc that instantiates an Array struct, determines the data type and returns an Array data type to a user.
append_array which allows a user to dynamically grow an array one index at a time, or add an already defined array.
free_array which frees all memory and resets struct variables
int_array_val which typecasts the data at an index and returns to user. I have versions of this function for all relevant data types, but for this problem I will only use this version.
find_int_array_indices which looks for where a specific integer exists in the array and records the index number into another array which is returned to the user.
For the purposes of testing find_int_array_indices I am calling init_array for a variable titled arr_test and appending it with 7 integers int a[7] = {6, 1, 3, 6, 6, 4, 5}. I pass the Array container arr_test to the find_int_array_indices function and everything works fine, which also returns another Array container titled p. However, when I try to retrieve the integer variables with the int_array_val function it fails, because it does not recognize the variable array->dtype as containing the string "int". However, when I test the container inside of find_int_array_indices and in the main function, the variable does contain the string "int". This tells me that I probably have a pointer error, but I do not see it. Any advice would be very useful. I am wondering if I need to go back to the beginning and define name and dtype as fixed length arrays in the Array struct instead of as pointer variables.
array.h
typedef struct
{
void *array; // Pointer to array
size_t len; // Active length of array
size_t size; // Number of allocated indizes
int elem; // Memory consumption per indice
char *name; // The array name
char *dtype; // A string representing the datatype
} Array;
void array_mem_alloc(Array *array, size_t num_indices);
Array init_array(char *dtype, size_t num_indices, char *name);
int append_array(Array *array, void *elements, size_t count);
void free_array(Array *array);
int int_array_val(Array *array, int indice);
Array find_int_array_indices(Array *array, int integer);
array.c
void array_mem_alloc(Array *array, size_t num_indices) {
// Determine the total memory allocation and assign to pointer
void *pointer;
pointer = malloc(num_indices * array->elem);
// If memory is full fail gracefully
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
free(pointer);
exit(0);
}
// Allocate resources and instantiate Array
else {
array->array = pointer;
array->len = 0;
array->size = num_indices;
}
}
// --------------------------------------------------------------------------------
Array init_array(char *dtype, size_t num_indices, char *name) {
// Determine memory blocks based on data type
int size;
if (strcmp(dtype, "float") == 0) size = sizeof(float);
else if (strcmp(dtype, "int") == 0) size = sizeof(int);
else if (strcmp(dtype, "double") == 0) size = sizeof(double);
else if (strcmp(dtype, "char") == 0) size = sizeof(char);
else {
printf("Data type not correctly entered into init_array, exiting program!\n");
exit(0);
}
// Allocate indice size and call array_mem_alloc
Array array;
array.dtype = dtype;
array.elem = size;
array_mem_alloc(&array, num_indices);
array.name = name;
return array;
}
// --------------------------------------------------------------------------------
int append_array(Array *array, void *elements, size_t count) {
// Allocae more memory if necessary
if (array->len + count > array->size) {
size_t size = (array->len + count) * 2;
void *pointer = realloc(array->array, size * array->elem);
// If memory is full return operations
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
return 0;
}
// Allocate memory to variables and increment array size
array->array = pointer;
array->size = size;
}
// Append variables and increment the array length
memcpy((char *)array->array + array->len * array->elem, elements, count * array->elem);
array->len += count;
return 1;
}
// --------------------------------------------------------------------------------
void free_array(Array *array) {
// Free all memory in the array
free(array->array);
// Reset all variables in the struct
array->array = NULL;
array->size = 0;
array->len = 0;
array->elem = 0;
}
// --------------------------------------------------------------------------------
int int_array_val(Array *array, int indice) {
// Ensure array contains integers
printf("%s\n", array->dtype);
if (strcmp(array->dtype, "int") != 0) {
printf("Function can only return integer values, exiting function!\n");
exit(0);
}
// Cast value to an integer and return
int a = ((int *)array->array)[indice];
return a;
}
Array find_int_array_indices(Array *array, int integer) {
int number = 0;
int input;
for (int i = 0; i < array->len; i++) {
if (integer == int_array_val(array, i)) {
number++;
}
}
char dtype[7] = "int";
char name[9] = "indices";
Array indice_arr = init_array(dtype, number, name);
for (int i = 0; i < array->len; i++) {
input = i;
if (integer == int_array_val(array, i)) {
append_array(&indice_arr, &input, 1);
}
}
return indice_arr;
}
main.c
size_t indices = 10;
char name[6] = "array";
char dtype[7] = "int";
Array arr_test = init_array(dtype, indices, name);
int a[7] = {6, 1, 3, 6, 6, 4, 5};
append_array(&arr_test, a, 7);
Array p = find_int_array_indices(&arr_test, 6);
printf("%s\n", p.dtype); // This shows that p does contain dtype "int"
int d = int_array_val(&p, 0); // This fails in function, because it does not see dtype = "int"???
printf("%d\n", d);
In find_int_array_indices
char dtype[7] = "int";
char name[9] = "indices";
are both local variables, which are invalidated when the function returns. See: Dangling pointer and Lifetime.
init_array uses these values as if they had a lifetime to match its return value
Array array;
array.dtype = dtype;
array.elem = size;
array_mem_alloc(&array, num_indices);
array.name = name;
return array;
which, as a structure type, is a lifetime determined by the context of its caller (return is copy, after all).
find_int_array_indices completes the error when it returns indice_arr to main.
Some options:
Strictly use pointers to strings with static storage duration.
Change your structure definition to include space for these strings (or allocate it), and perform string copies.
Use an enumerated type instead.
Ditch this string-based, type limited paradigm all together by supporting all memory sizes generically (the naming feature remains an issue, though).
A rather long-winded continuation, to elaborate on using enumerated types:
The idea is to define a smaller set of acceptable values that your library works with, and making the user more aware of these values. As we can see, you have partially done that using strings but the implementation has some issues, as strings are generally clunky. Some problems with strings:
you have no control over the strings that users of your library use (this leads you to have to exit1 the program in the event the users enters something unexpected, which is easy to do),
you must account for their potentially large or excess memory consumption,
string comparison is O(N),
strings are generally unsafe in C, requiring more care than other basic constructs when handling them (assignment, comparison, storage).
So instead of using strings ("foo", "bar", "qux" in these examples), we use an enumerated type
enum OBJECT_TYPE {
OBJECT_FOO,
OBJECT_BAR,
OBJECT_QUX
};
which establishes the following:
it is more clear what the acceptable values are
some2 control over what users enter, via type hinting
comparison is O(1)
handling is the same as any integral type
The structure definition then looks like
typedef struct {
/* ... whatever members are needed for the structure */
size_t something_based_on_type;
enum OBJECT_TYPE type;
char debug_name[MAX_DEBUG_NAME];
} Object;
Nothing can really be done about the name member of your structure. If you want user defined nametags for things, then yes, as stated previously, you need to allocate space for them.
Our initialization function works similarly, but we can2 take advantage of some properties of integral types.
void object_init(Object *object, enum OBJECT_TYPE type, const char *debug_name) {
/* ... accept other arguments, whatever is needed to initialize */
size_t value_translations[] = { 42, 51, 99 };
object->type = type;
/* while neat, this is somewhat naive, see footnotes */
object->something_based_on_type = value_translations[type];
if (debug_name && strlen(debug_name) < MAX_DEBUG_NAME)
strcpy(object->debug_name, debug_name);
else
*object->debug_name = '\0';
}
Now we want to provide a function that works with our generic data of only type OBJECT_FOO (like your int_array_val). Again, the comparison is much easier to understand.
void object_print_foo(Object *o) {
if (OBJECT_FOO != o->type)
/* handle type mismatch */;
}
Although it would be better to provide a generic object_print function that again branches based on o->type.
A main function for completeness:
int main(void) {
Object a;
object_init(&a, OBJECT_QUX, "object_a");
object_print_foo(&a);
}
This is the general idea of using enumerated types.
With all that said, I think this is not really any better than just handling arbitrary data sizes, risks included. Something like
const void *array_get(Array *array, size_t index) {
if (index >= array->length)
return NULL;
return (char *) array->array + index * array->elem;
}
works, if the user respects the const contract, and uses the correct types (they would need to remember their typing with specifically typed getters too).
Generic data structures in C are a bit of a leap of faith no matter what.
1. So a note on exiting from library code: don't. As a library author, you have no reasonable right to cause user programs to terminate (unless requested, or the user invokes UB outside your control). Delegate upwards, return errors, and let the user exit the program on their own terms, as they may need to perform their own cleanups (or might carry on if the failure is non-critical).
2. C's enumeration type is rather weak. enum are actually just int, and users can enter plain integer values outside the specified ranges. This is akin to invoking undefined behavior from a library's point of view, but we may wish to protect the user anyway.
I want to pass this in my function, but something is going wrong
FILE *f = fopen("out.bmp", "rb");
int countBit = 0;
int size = 0;
char* type;
for (int i = 0; i < 54; i++)
fgetc(f);
printf("/* count bit to pixel */\n");
scanf("%d", &countBit);
size=DecodeInformationSize(f, countBit);
type=DecodeInformationType(f, countBit);
DecodeMessage(f,countBit,size,type);
before entering the function type is txt
but after :
void DecodeMessage(FILE *f, int countBit, int size, char* type)
{
char messageSize[8];
char nameOut[15] = "outMessage.";
strcat(nameOut, type);
char* message = (char*)malloc(size * 8);
please explain problem
To be absolutely sure we need to know what DecodeInformationType(f, countBit); does.
However, it seems it uses some data on the stack. Once it returns, this information may only be available for a few instructions. So your debugger shows that the call to DecodeMessage, type points to a valid string, but once you enter DecodeMessage, the stack is overwritten with the variables of DecodeMessage, in particular with char nameOut[15] = "outMessage.";
To solve this, make sure that DecodeInformationType returns a pointer to memory that is not on the stack (not an automatic variable) of DecodeInformationType. That could be memory allocated with malloc or a constant string.
I have the following structs in my on-going struggle to eventually create some kind of shell (based eventually around execvp().
struct commands {
char cmdname[30]; // The name of the command
enum ActionType action; /* char action[30]; what action to take */
};
struct userinput {
struct commands theaction; //The chosen action
char cmdentered[100]; // The cmd entered
char **anyargs; //The tokenised command
int argcount; //Argument count
};
And I initialise anyargs using malloc and create an array of strings with one string per argument to be passed on to the execvp.
I then get user input, convert the input into tokens stored in anyargs and examine the strings to find out what sort of action needs to be taken and store that in an enum.
All these methods are done by passing the pointer to the struct userinput as method parameters - which works fine. HOWEVER when I pass the pointer to the struct to a nested function, the char** anyargs becomes empty.
I hope the code I've added provides a solution to the answer! On another observation - when passed to a function inside a function, the actual value of the pointer doesn't change - only the dereferenced contents of the pointer.
Any help would be most gratefully received! I've tried to strip the code down to the areas I think are causing the issue!
Thank you!
int main() {
struct commands cmdlist[4]; //Array of structures with all commands in them
memset(cmdlist, 0, sizeof(cmdlist));
struct userinput userentry = { { { 0 } } }; //Structure containing input
userentry.theaction = cmdlist[0]; //Initialize empty command
userentry.anyargs = calloc(100, sizeof(char));
runEntry(&userentry, cmdlist); //Pass struct to function
free(userentry.anyargs);
return 0;
}
int runEntry(struct userinput *userentry, struct commands thecmds[]) {
int retval = 0;
int childpid = 0;
int processStatus;
printf("\n ... running cmd: \n\n");
printUserEntry(userentry); //in printUserEntry,
//userentry->anyargs[0] = NULL - why?
}
You've allocated 100 bytes worth of char * elements in anyargs. You haven't initialized those pointers, though. The fact that anyargs[0] happens to contain NULL is nice, but not guaranteed. malloc() doesn't initialize the allocated space.
In other words, when you say:
userentry.anyargs = malloc(100);
you've created:
userentry.anyargs = {
???, // uninitialized char *
???, // and another
???, // and another
...
??? // (100 / sizeof(char *)) entries later
};
You can explicitly initialize those to NULL in a loop:
for ( i = 0; i < (100 / sizeof(char *)); ++i )
userentry.anyargs[i] = NULL;
(or use calloc() instead of malloc() to ensure everything is zeroed out).
or you can allocate some space to them:
for ( i = 0; i < (100 / sizeof(char *)); ++i )
userentry.anyargs[i] = malloc(50); // or some other length
or just set them directly in runEntry():
userentry.anyargs[0] = "foo";
userentry.anyargs[1] = strdup(something);
#include<stdio.h>
#define SIZE 3
int main()
{
char intArrayOne[SIZE] = {'A', 'B', 'C'};
char (*ptrToAnOneDimArray)[SIZE] = &intArrayOne;
int i = 0;
for(i=0 ; i<SIZE ; i++)
{
printf("%c ", (*ptrToAnOneDimArray)[i]);
}
}
Output
A B C
When should we use "ptrToAnOneDimArray" - kinds of usages in C/C++? Please give me a real-world example.
Can we avoid these kinds of complex and fuzzy usages of pointers?
For example, when you want to implement a dynamic multidimensional array:
int (*ptrArr)[WIDTH] = malloc(sizeof ptrArr[0] * HEIGHT);
is much better than
int **ptrPtr = malloc(sizeof ptrPtr[0] * HEIGHT);
for (size_t i = 0; i < HEIGHT; i++) {
ptrPtr[i] = malloc(sizeof ptrPtr[0][i] * WIDTH);
}
for various reasons (it does actually point to a 2D array that is contiguous in memory, it requires less allocations and frees, so it's less likely that you get it wrong, etc.)
Suppose that you are embedded programmer. Now you have some piece of hardware with exchangable modules. With each module you must communicate differently ie. you init/read/write to/from it differently.
Now you have your software that must handle all of these module types. You have 3 routines (simplified here) to init, read, write each type module (HW0 is module A, HW1 is module B).
void HW0_init() { printf("HW0_init\n"); }
void HW0_read() { printf("HW0_read\n"); }
void HW0_write(){ printf("HW0_write\n"); }
void HW1_init() { printf("HW1_init\n"); }
void HW1_read() { printf("HW1_read\n"); }
void HW1_write(){ printf("HW1_write\n"); }
Now imagine you want to init your module and read sth from it so you do:
int hw_id = 1;
// want to init hardware
switch(hw_id)
{
case 0: HW0_init(); break;
case 1: HW1_init(); break;
// ...
}
// now I want to read
switch(hw_id)
{
case 0: HW0_read(); break;
case 1: HW1_read(); break;
// ...
}
This may be accomplished differently using pointers to arrays. If you declare arrays of pointers to your functions like so:
// as many arrays as you have modules
void (*hw0[3])() = { HW0_init, HW0_read, HW0_write };
void (*hw1[3])() = { HW1_init, HW1_read, HW1_write };
your code may be simplified to this:
enum HW_ACTION
{
HW_INIT = 0,
HW_READ = 1,
HW_WRITE = 2
};
// pointer to array of pointers to funcs taking nothing
// and returning nothing
void (*(*f)[3])(void);
// detect hardware and set 'f'
f = &hw1;
(*f)[HW_INIT](); // same as HW1_init(); <=> hw1[HW_INIT]();
(*f)[HW_READ](); // same as HW1_read(); <=> hw1[HW_READ]();
Same effect - 'easier code'.
You may treat it as poor's man virtual methods for C users having no C++ compiler where you would normally create base abstract class with init, read, write methods and implement them for every kind of module.
Real life here http://en.wikipedia.org/wiki/Virtual_method_table.
Pointers-to-pointers (hence pointers-to-arrays by proxy) are really useful. If you have a function/method and it takes a pointer-to-value argument you can change the value inside your function and that value stays in scope after you leave the function - pass-by-reference of course. However you can't change the address your pointer points at - e.g. make the pointer you passed into a NULL pointer, or point it at a different value somewhere else in memory. If you use a pointer-to-pointer-to-value then you can change the value of the 'middle' pointer inside your function. I think the MySQL C-connector library is an example of where this is used.
In your example you could pass ptrToAnOneDimArray into a function and make *ptrToAnOneDimArray be a NULL pointer or a pointer to some other data rather than intArrayOne - as intArrayOne is a fixed size by the compiler (on the stack) then you could dynamically update *ptrToAnOneDimArray from the stack to be an array malloc()'d on the heap.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 3
void display(char* data) {
int i = 0;
for(i=0 ; i<SIZE ; i++) {
printf("%c ", data[i]);
}
}
void changeMyArgument(char** pointerToPointer) {
*pointerToPointer = (char*) malloc(SIZE * sizeof(char));
/* now we use array notation for a change */
(*pointerToPointer)[0] = 'X';
(*pointerToPointer)[1] = 'Y';
(*pointerToPointer)[2] = 'Z';
}
int main() {
/* intArrayOne is implicitly char* */
char intArrayOne[SIZE] = {'A', 'B', 'C'};
char* arraysArePointers = intArrayOne;
/* ptrToAnOneDimArray is implicitly char** */
char** ptrToAnOneDimArray;
ptrToAnOneDimArray = &arraysArePointers;
display(*ptrToAnOneDimArray);
changeMyArgument(ptrToAnOneDimArray);
display(*ptrToAnOneDimArray);
}
I have utitlity function which gives me a char buffer of individual bytes, when I provide it with a structure.
unsigned char complete[16] = { 0 };
char* construct_complete_array(socketType* m)
{
unsigned char *temp = (unsigned char*) m;
size_t j;
for (j = 0; j < sizeof(*m); j++)
{
complete[j] = *(temp);
printf("%.2x ", *(temp));
*temp++;
}
return complete;
}
int diff_bit_calc(socketType* datanode, socketType* knode)
{
char* result = construct_complete_array(datanode);
size_t j;
printf("\nPrinting result: \n");
for (j = 0; j < sizeof(*datanode); j++)
{
printf("%.2x ", *(result));
*result++;
}
}
I want it to be a generic function which when provided with a structure will return me a char buffer of the structure.
I might have another invocation like
char* result1 = construct_complete_array(knode);
(I don't think having complete[16] buffer as global a good idea. Having it local and returning it is still a worser idea. )
In general, you can't do that without dynamically allocating memory. Most people get around it by declaring the buffer in the calling function and passing that buffer to a function, which will then fill in the passed buffer.
In your specific case, I'm not so sure a function is necessary; it's rather short to do it inline, e.g.:
/* to get the bytes representing `something' into a char array */
char something_chars[sizeof(something)];
memcpy(something_chars, &something, sizeof(something));
As for as I know, there are two ways to do that.
Since the return value of the function is a pointer, so you must make sure that the memory you store result won't be destroyed. Other than using global variable, you can use dynamic allocating memory(like icktoofay said) or static keyword
(like Tay Wee Wen said).
When using dynamic allocating memory, the user of this function should remember to free() outside the function.
When using static keyword inside the block, there is a problem of overriding. If you call the function several times, only the last return value was kept.
By the way, *temp++; is a little strange, why not use temp++; instead.
Declare the array static inside the function.
char* construct_complete_array(socketType* m){
static unsigned char complete[16]= {0};
unsigned char *temp = (unsigned char*)m;
size_t j;
for (j = 0;j<sizeof(*m);j++){
complete[j] = *(temp);
printf("%.2x ", *(temp));
*temp++;
}
return complete;
}
You'd have to change your interface a bit:
char* construct_complete_array(socketType* m, char temp[]);
then on the calling side you can use a compound literal to provide temp
char* result = construct_complete_array(datanode, (char[sizeof *datanode]){ 0 });
If you have to repeat that in several places you could put that into a macro
#define CONSTRUCT_ARRAY(X) construct_complete_array((X), (char[sizeof *(X)]){ 0 })
so then again your call side looks almost as you had it before
char* result = CONSTRUCT_ARRAY(datanode);
For this to work you just have to have in mind that the value in result points to local data with the same life time as result itself.