I write generic application for handle as many modbus devices as defined in JSON config file.
mbus_servers struct used in my_modbus_init() contents ip of device and port.
Initialization of one modbus_t in my_modbus_init() looks like this:
modbus_t * my_modbus_init(const char * ip_s, int port, int slave_id)
{
modbus_t *ctx;
ctx = modbus_new_tcp(ip_s, port);
if(ctx == NULL)
{
printf("Error");
}
modbus_set_debug(ctx, 0);
if (modbus_connect(ctx) == -1)
{
fprintf(stderr, "Connection failed: %s\n",modbus_strerror(errno));
modbus_free(ctx);
return NULL;
}
modbus_set_slave(ctx, slave_id);
return ctx;
}
Now I try to initialize dynamiclly allocated number of modbus_t:
modbus_t * my_modbus;
int quantity_of_connections_modbus = 3;
my_modbus = (modbus_t *) malloc (quantity_of_connections_modbus * sizeof(modbus_t));
^here I get invalid application of ‘sizeof’ to incomplete type ‘modbus_t' (I know that is because i dont have acces to definition of modbus_t [it is defined in modbus.h as typedef struct _modbus modbus_t; ])
for(i=0; i< quantity_of_connections_modbus; i++)
{
// |> my_modbus[i] = my_modbus_init(mbus_servers[i]->host,mbus_servers[i]->port,MBUS_SLAVE);
// |- And here error: dereferencing pointer to incomplete type ‘modbus_t {aka struct _modbus}’
}
Is there any way to create as many modbus_t as needed using malloc?
Instead of having an array of modbus_t objects, have an array of pointers to modbus_t objects. This makes sense since the my_modbus_init function (and the modbus_new_tcp function it calls) returns pointers.
In other words change sizeof(modbus_t) to sizeof(modbus_t *). And change the variable my_modbus to represent this array of pointers (i.e. be a modbus_t **).
The code from the question modified accordingly:
modbus_t ** my_modbus;
int quantity_of_connections_modbus = 3;
my_modbus = malloc (quantity_of_connections_modbus * sizeof(modbus_t*));
for(i=0; i< quantity_of_connections_modbus; i++)
{
my_modbus[i] = my_modbus_init(mbus_servers[i]->host,mbus_servers[i]->port,MBUS_SLAVE);
}
Related
Trying to add another element to a struct array in C (Windows specific, using VS2019 Community). Works fine, until I try to assign the return value of realloc to the original array. The code in main (declarations and initialization, as well as calling code) is as follows:
// server.h
struct server {
wchar_t* name;
wchar_t ip_address[16];
int port;
};
// main.c
static int nb_servers = 0;
static struct server* servers = NULL;
void add_server(wchar_t* name, wchar_t ip_address[16], wchar_t* port)
{
struct server newserver;
newserver.name = name;
wcsncpy(newserver.ip_address, ip_address, 16);
char* port_char = malloc(6);
if (port_char == NULL) {
exit(EXIT_FAILURE);
}
size_t i;
wcstombs_s(&i, port_char, 6, port, _TRUNCATE);
int port_int = 0;
str2int(&port_int, port_char, 10);
newserver.port = port_int;
// add to servers
nb_servers = server_add(&servers, &newserver, nb_servers);
}
Then in another file, this is where I try to add the new server to the list:
// server.c
int server_add(struct server** servers, struct server* myserver, int nb_servers)
{
struct server* tmp = (struct server*) realloc(*servers, (nb_servers + 1) * sizeof(struct server));
if (tmp == NULL) {
exit(EXIT_FAILURE);
}
tmp[nb_servers].name = (wchar_t*) calloc(strlen(myserver->name), sizeof(wchar_t));
if (tmp[nb_servers].name == NULL) {
exit(EXIT_FAILURE);
}
wcsncpy(tmp[nb_servers].name, myserver->name, strlen(myserver->name));
wcsncpy(tmp[nb_servers].ip_address, myserver->ip_address, 16);
tmp[nb_servers].port = myserver->port;
*servers = tmp; // this only copies the first value [0]
// also tried **servers = *tmp and other combinations, nothing seems to work.
return ++nb_servers;
}
But only the first value is 'copied', or rather only servers[0] point to a valid object. However, tmp[0] to tmp[nb_servers - 1] are valid and contain the correct data. I'm using a similar reallocation mechanism to shrink the array in a remove_server method and that same reassignment works in that case.
Question:
How to correctly add a struct item to an array of structs by dynamically reallocating memory?
I am working on an assignment which requires me to use threads to process and synchronize fetching data from a file. My professor told me that I can change my data to a void pointer to pass it to my function and then cast it back. I am trying to do this with file IO.
pthread_create(&th1, NULL, processing, (void *)&fp);
In my processing function I am trying to cast it back to a FILE pointer with this:
FILE driveOne = (FILE *)file;
This clearly doesn't work, so can someone explain this to me?
Here's a more complete example.
Let's say your worker function needs a file handle. For simplicity, let's say it reads each char from it, and returns the number of chars read, cast to a pointer:
void *worker(void *data)
{
FILE *handle = (FILE *)data;
uintptr_t count = 0;
if (handle && !ferror(handle)) {
/* handle is a valid file handle */
while (getc(handle) != EOF)
count++;
}
return (void *)count;
}
If count were of some other type than intptr_t or uintptr_t (declared in <stdint.h>, which is typically included by including <inttypes.h>), you'd need to cast it first to that type, and then to void pointer, i.e. (void *)(uintptr_t)count.
Because such worker threads don't need much stack (almost none, to be precise), and default thread stack sizes are huge (megabytes), we can save some memory (and allow much more threads if needed, especially on 32-bit architectures) by creating a pthread attribute that instructs pthread_create() to use a smaller stack. This attribute is not "consumed" by the call; it is more like an configuration block.
Let's say you have three streams, FILE *in[3];, and you wish to use three threads to check their lengths. Using a pthread attribute to use a smaller stack (2*PTHREAD_STACK_MIN, as defined in <limits.h>, is a good, safe value for worker threads that don't use alloca() or local arrays.):
pthread_t worker_id[3];
uintptr_t length[3];
pthread_attr_t attrs;
void *retptr;
int i, result;
/* Create a pthread attribute set, defining smaller stack size. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2*PTHREAD_STACK_MIN);
/* Create the three worker threads. */
for (i = 0; i < 3; i++) {
result = pthread_create(&(worker_id[i]), &attrs, worker, (void *)in[i]);
if (result) {
fprintf(stderr, "Cannot create thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
}
/* pthread attributes are no longer needed. */
pthread_attr_destroy(&attrs);
/*
... This thread can do something else here ...
*/
/* Reap the threads, and collect their return values. */
for (i = 0; i < 3; i++) {
result = pthread_join(worker_id[i], &retptr);
if (result) {
fprintf(stderr, "Cannot reap thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
length[i] = (uintptr_t)retptr;
}
for (i = 0; i < 3; i++)
printf("in[%d] contained %llu chars.\n", i, (unsigned long long)length[i]);
The same pattern can be used when you want to pass multiple parameters to the thread function. You first construct a structure to hold those parameters, and create them. You can allocate them dynamically, declare them as global variables, or declare them as local variables in main() -- any scope that exists for the full duration when the worker thread exists, works.
For example, let's say your worker function calculates a histogram of each unsigned char value it reads from the stream:
struct work {
pthread_t id; /* Thread identifier */
FILE *in; /* File handle to read from */
size_t count[UCHAR_MAX + 1]; /* Histogram */
};
void *worker(void *data) {
struct work *const work = (struct worker_data *)data;
int c;
if (!work || !work->in) {
/* Invalid data, or invalid file handle. */
return (void *)(intptr_t)(EINVAL);
}
if (ferror(work->in)) {
/* Stream is in error state. */
return (void *)(intptr_t)(EIO);
}
/* Read the stream. */
while ((c = getc(work->in)) != EOF) {
/* Update histogram. */
work->count[(unsigned char)c]++;
}
/* Did the reading stop due to an I/O error? */
if (ferror(work->in))
return (void *)(intptr_t)(EIO);
/* No errors, all done. */
return (void *)0;
}
Note that struct work *const work = ... initializes a constant pointer work, not a pointer to constant. The const there is just an optimization that tells the C compiler that we won't try to modify work pointer itself. The data it points to, is modifiable.
(To read pointer declarations, read them from right to left, replacing each * with "is a pointer to", to get the proper sense of it.)
The code to create these workers is very similar, except that we allocate the work dynamically:
struct work *work[3];
pthread_attr_t attrs;
void *retptr;
int i, result;
/* Create and initialize the three pointers. */
for (i = 0; i < 3; i++) {
/* Allocate a work structure. */
work[i] = malloc(sizeof *(work[i]));
if (!work[i]) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
/* Copy the handle to read from, */
work[i]->in = in[i];
/* and clear the histogram part. */
memset(work[i]->count, 0, sizeof work[i]->count);
}
/* Create a pthread attribute set, defining smaller stack size. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2*PTHREAD_STACK_MIN);
/* Create the three worker threads. */
for (i = 0; i < 3; i++) {
result = pthread_create(&(work[i]->id), &attrs, worker, (void *)work[i]);
if (result) {
fprintf(stderr, "Cannot create thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
}
/* pthread attributes are no longer needed. */
pthread_attr_destroy(&attrs);
/*
... This thread can do something else here ...
*/
/* Reap the threads, and collect their return values. */
for (i = 0; i < 3; i++) {
result = pthread_join(work[i]->id, &retptr);
if (result) {
fprintf(stderr, "Cannot reap thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
/* If the thread reported a failure, print the corresponding
error message (but do not exit). */
if (retptr)
fprintf(stderr, "Thread %d of 3: %s.\n", i+1, strerror((intptr_t)retptr));
/* ... print the histogram here? ... */
}
/* Free the work structures. */
for (i = 0; i < 3; i++)
free(work[i]);
If you don't want to abort the program when an error occurs, it is useful to note that free(NULL) is safe and does nothing; and that struct work *pointerarray[SIZE] = {0}; declares an array of SIZE pointers to struct work, and initializes them all to zero. For example, if an allocation or thread creation fails at some point, you can just free() each pointer, whether or not its allocation was successful.
That is, if you want to allocate three different types of structures (struct atype *a;, struct btype *b;, and struct ctype *c;), you can do
a = malloc(sizeof *a);
b = malloc(sizeof *b);
c = malloc(sizeof *c);
if (!a || !b || !c) {
free(c);
free(b);
free(a);
return ALLOCATION_FAILED;
}
/* Allocation was successful */
instead of allocating each one and testing for failure separately.
You need to declare driveOne to be FILE *, not FILE.
FILE *driveOne = (FILE *)file;
In addition, assuming that fp was initially declared as FILE *, your call to pthread_create should not have & before fp, like so:
pthread_create(&th1, NULL, processing, (void *)fp);
below is C snippet from mongoose webserver http event handler I am working on:
static void HttpEventHandler(struct mg_connection *nc, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) ev_data;
if (mg_vcmp(&hm->method, "POST") == 0) {
pthread_t thread_id;
int rc;
rc = pthread_create(&thread_id, NULL, thr_func, /* Here I want hm body to be passed after its malloced */);
if (rc) { /* could not create thread */
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
return EXIT_FAILURE;
}
}//if POST
mg_printf(nc, "HTTP/1.1 200 OK\r\n");
nc->flags |= MG_F_SEND_AND_CLOSE;
}
}
the http post message body, accessible as string using below syntax:
"%.*s", (int) hm->body.len,hm->body.p
I want code sample to malloc hm->body and pass it to the thread in snippet above, also it would be great to explain how to cast the passed void *. if its difficult then please malloc ev_data or hm.
You'd malloc() it as in:
hm->body = malloc(sizeof *(hm->body));
hm->body.p = "string";
/* The above assigns a string literal. If you need to copy some
user-defined string then you can instead do:
hm->body = malloc(size); strcpy(hm->body.p, str);
where 'str' is the string you want copy and 'size' is the length of 'str'.
*/
hm->body.len = strlen(hm->body);
and then pass it to:
rc = pthread_create(&thread_id, NULL, thr_func, hm->body);
In thr_func() you would need to convert the argument to whatever the type of hm->body and then access it (because void * can't be dereferenced directly.). Something like:
void *thr_func(void *arg)
{
struct mg_str *hm_body = arg;
printf("str: %s, len: %zu\n", hm_body->p, hm_body->len);
...
return NULL;
}
There's no need to cast anything to void*. The pthread_create() API expects a void * as the last argument and any data
pointer can be directly assigned to void *. The same applies to struct http_message *hm = (struct http_message *) ev_data; statement as well.
It can be just: struct http_message *hm = ev_data;.
Depending how the "webserver" is implemented, you might need to take care of thread(s) completion as well.
P.S: If you show the "hm" structure, it'll be much easier to explain things.
I have been trying to pass an array of strings into a function that finds all of the IP addresses of the host. My problem is immediately after I fill the array up with the addresses the contents are changed unexpectedly. I print the contents of the array immediately after I assign a string to one part of the array, this is how I know I am initializing the array. Then after the loop is done I try accessing all of the addresses in the array and all of the values are changed to the value I last passed into the array. Why is this? What am I doing wrong?
Here is the function:
static int getHostIP(char*ip_list[])
{
char hostName[80];
if(gethostname(hostName, sizeof(hostName)) == SOCKET_ERROR)
{
printf("Error %s when getting host name.\n", WSAGetLastError());
return 1;
}
printf("Hostname: %s\n", hostName);
struct addrinfo *result = NULL;
if(getaddrinfo(hostName,NULL, NULL, &result) == 1)
{
printf("Error %s when getting host address info.\n", WSAGetLastError());
return 1;
}
//iterate over IP addresses
struct addrinfo *ptr;
int x = 0;
for(x = 0,ptr = result; ptr != NULL;ptr = ptr->ai_next, x++)
{
struct sockaddr_in *hostaddr = (struct sockaddr_in*)ptr->ai_addr;
char ip_addr[80];
inet_ntop(ptr->ai_family,(void*)&hostaddr->sin_addr, ip_addr, sizeof(ip_addr));
ip_list[x] = ip_addr;
}
int i;
for(i = 0; i < 7;i++)
{
printf("IP: %s\n", ip_list[i]);
}
return 0;
}
EDIT
Calling code:
char * ip_list[80] = {0};
//TODO: Get Host IP address
if(getHostIP(ip_list) == 1) return 1;
The behaviour you are experiencing is caused by the variable ip_addr which is always pointing to the same buffer in the stack during each iteration. Thus, all pointers in ip_list are pointing to the same buffer which contains the value calculated in the last iteration of the loop.
If you allocate this buffer in the heap by using malloc the problem should be solved because,now the loop block will create a new buffer for each ip. For example :
#define BUFFER_SIZE 80 // no in the function body
char * ip_addr = NULL;
for(x = 0,ptr = result; ptr != NULL;ptr = ptr->ai_next, x++)
{
ip_addr = malloc(BUFFER_SIZE);
struct sockaddr_in *hostaddr = (struct sockaddr_in*)ptr->ai_addr;
inet_ntop(ptr->ai_family,(void*)&hostaddr->sin_addr, ip_addr, BUFFER_SIZE);
ip_list[x] = ip_addr;
}
How is your data allocated ?
Try with:
static int getHostIP(char**ip_list)
Are you properly initializing the array you are passing in to this function. You are declaring an input of an array of char pointers. When ever you pass an array in c you must also pass along the length the array was initialized with. The memory needs to live somewhere and be reserved by the system.
Can you please provide the calling code so we can see what you are doing wrong.
Alternatively --- you could pass this entire array byref so you would just be getting an out pointer and the array would be declared by this function. Since you have no idea how many IP addresses you might match that might be a superior design.
I'm experiencing odd behavior in Eclipse / C. I have the following type declared in, lets say, a.h.
typedef double sig_type[3];
and the following in, lets say, b.c
typedef struct filter_kind {
. . .
sig_type * fil_buff; //The buffer for all values
. . .
} filter_kind;
int init_filter(filter_kind * filter, const sig_type init_data[],
const int data_len) {
if (filter->data_buff_len != data_len) {
return -1
}
int i;
int j;
for (i = 0; i < filter->data_buff_len; i++) {
for (j = 0; j < OUT_NUM; j++) {
(filter->fil_buff)[i][j] = init_data[i][j]; //prog exits on this line.
}
}
filt_coeffs(filter);
return 0;
}
I have a specified function to return a pointer to a malloced filter_kind structure, which mallocs fil_buff. When I use this creation function, and pass the newly created filter_kind pointer to init_filter, the function unexpectedly exits when assigning to (filter->fil_buff)[][] -- with almost no note other than "gdb" in the Debug view.
I've dropped in some probe variables, and viewed them during debug, and nothing seems abnormal up until this point. I can read from the array fine, just cannot assign. Am I doing something wrong here?
And lastly, here is the constructor function with corresponding allocation functions.
filter_kind * create_filter(const double f_lo, const double f_hi,
const double samp_r, win_type window_t, fil_type filter_t,
const int buff_len) {
filter_kind * filter;
sig_type * fil_buff;
int err = 0;
/* allocate filter struct */
filter = (filter_kind *) malloc(sizeof(filter_kind));
err = (filter != NULL ) ? 0 : -1;
if (err == -1) {
return NULL ;
}
memset(filter, 0, sizeof(filter_kind));
/* allocate filter data members */
err = alloc_buffs(win_coeffs, fil_coeffs, fil_buff, buff_len);
if (err == -1) {
return NULL ;
}
//assign other structure values...
filter->fil_buff = fil_buff;
return filter;
}
static int alloc_buffs(double * win_coeffs, double * fil_coeffs,
sig_type * fil_buff, const int buff_len) {
int err = 0;
//allocate other buffers...
err = alloc_st_buff(fil_buff, buff_len);
if (err == -1) {
return -1;
}
return 0;
}
static int alloc_st_buff(sig_type * st_buff, const int buff_len) {
const int num_bytes = sizeof(sig_type) * buff_len;
st_buff = (sig_type *) malloc(num_bytes);
const int err = (st_buff != NULL ) ? 0 : -1;
if (err == -1) {
return -1;
}
memset(st_buff, 0, num_bytes);
return 0;
}
and for what it's worth, designed to be used as follows
filter_kind * filter;
filter = create_filter(...);
/* Load data into array of sig_type, i.e. sig_type arr[40] */
init_filter(filter, arr, 40);
/* more code... */
Ok problem is with allocating buffers (calling allocating function):
sig_type * fil_buff;
err = alloc_buffs(win_coeffs, fil_coeffs, fil_buff, buff_len);
filter->fil_buff = fil_buff;
So what is happening here:
Create pointer to a table called fil_buff,
call function alloc_buffs with copies of pointers to fil_buff etc.,
assign not changed fil_buff to a structure.
Every time function takes argument it makes a copy of it. So when you passed a pointer, then function made a copy of this pointer (and it was operating on a copy of the pointer), thus original pointer (before function call) is not changed. You should pass pointer to the pointer you want to operate on. The way it could be done is:
err = alloc_buffs(win_coeffs, fil_coeffs, &fil_buff, buff_len);
^^^^^^^^^
then your fil_buff can really be changed, but you have to adjust your function to take proper arguments and to properly operate on them. I guess the same mistake has been made with other buffers.