A functional map is a function that applies a callback function to each element in an array and returns a list of callback return values. For example, in pseudocode, map(["hello", "world"], fn(x) => x + " meow") would return ["hello meow", "world meow"]
Since function pointers can be passed as parameters in C, it is possible to implement a functional map like below:
void** fp_map(void** array, size_t len, void* (*execute)(void*))
{
// Allocate memory for return items
void** returns = malloc(sizeof(void*) * len);
if (returns == NULL) err(42, "Malloc failed, buy more ram");
// Map values
for (int i = 0; i < len; ++i)
returns[i] = execute(array[i]);
return returns;
}
If I write the following anonymous function in my main method, it would map ["hello", "world"] to ["hello meow", "world meow"]:
int main() {
char* arr[] = {"hello", "world"};
char** arr2 = fp_map((void**) arr, 2, ({ void* _func_ (void* x) {
char* buf = malloc(sizeof(char) * (strlen(x) + 7));
strcpy(buf, x);
strcat(buf, " meow");
return buf;
}; _func_; }));
for (int i = 0; i < 3; ++i)
printf("%s\n", arr2[i]);
}
Now, I want to implement a parallel map to speed things up. Since this is purely functional, calls to the callback function with the same parameters would return the same return values. How can I use multithreading so that each call to execute() runs on a different thread, but still have the results return in an ordered array?
I have written the following code, in which I create a context for the thread, then for every calculation I spawn a separate thread. Join all the threads and return the value.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#define ERRORON(expr) \
do { \
if (expr) { \
fprintf(stderr, "ERROR: %s\n", #expr); \
exit(1); \
} \
} while (0)
#define ARRLEN(x) (sizeof(x) / sizeof(*x))
struct mythread_context {
void **returns;
void *(*execute)(void *);
void **array;
size_t i;
};
int mythread(void *arg) {
const struct mythread_context *ctx = arg;
// Execute the stuff to execute.
ctx->returns[ctx->i] = ctx->execute(ctx->array[ctx->i]);
return 0;
}
void **fp_map(void **array, size_t len, void *(*execute)(void *)) {
// Allocate memory for return items
void **returns = malloc(sizeof(*returns) * len);
ERRORON(!returns);
// Allocate memory for threads and contextes.
thrd_t *threads = malloc(sizeof(*threads) * len);
ERRORON(!threads);
struct mythread_context *ctxs = malloc(sizeof(*ctxs) * len);
ERRORON(!ctxs);
for (size_t i = 0; i < len; ++i) {
const struct mythread_context thisctx = {
.returns = returns,
.execute = execute,
.array = array,
.i = i,
};
ctxs[i] = thisctx;
// Start a thread for every returns, execute and array index.
int ret = thrd_create(&threads[i], mythread, &ctxs[i]);
ERRORON(ret != thrd_success);
}
for (size_t i = 0; i < len; ++i) {
// Join all threads. They will assing to returns separately concurrently.
int ret = thrd_join(threads[i], NULL);
ERRORON(ret != thrd_success);
}
free(threads);
free(ctxs);
return returns;
}
void *appnend_to_char(void *x) {
char *buf = malloc(sizeof(char) * (strlen(x) + 7));
strcpy(buf, x);
strcat(buf, " meow");
return buf;
}
int main() {
const char *arr[] = {"hello", "world"};
char **arr2 = (char **)fp_map((void **)arr, ARRLEN(arr), appnend_to_char);
for (size_t i = 0; i < ARRLEN(arr); ++i) {
printf("%s\n", arr2[i]);
}
// free memory
for (size_t i = 0; i < ARRLEN(arr); ++i) {
free(arr2[i]);
}
free(arr2);
}
Alternatively, you can just seamlessly integrate with OpenMP, with just:
void **fp_map(void **array, size_t len, void *(*execute)(void *)) {
void **returns = malloc(sizeof(*returns) * len);
ERRORON(!returns);
size_t i;
#pragma omp parallel for
for (size_t i = 0; i < len; ++i) {
returns[i] = execute(array[i]);
}
return returns;
}
Notes:
({ is a GCC extension, not part of C language. There are no lambdas or anonymous functions in C programming langauge.
I am not sure if C11 threads.h should be used or rather POSIX pthreads should be preferred. The interface is very similar.
The context is rather big, it could be optimized. The count of malloc coudl also be optimized.
Related
in my last question, I've asked how to use function to free an malloc'ed array, I wanted to improve my code so that the function won't just free the memory but also will set the pointer to NULL once it finishes the clearing.
Also I want a single function to do both - setting and clearing, depending on the command I'm passing, this is what I've done so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>
char **set_arr(int number, char *command);
int command_read(char *command);
void clear_arr(char *arr[], int size);
char set[] = "set";
char clear[] = "clear";
int main() {
int num = // get number from user;
char** my_arr = NULL;
my_arr = set_arr(num, set);
// so far the code works as excepted
set_arr((size_t)&my_arr, clear);
return 0;
}
int command_read(char *command) {
if (strcmp(command, set) == 0)
return 'S';
if (strcmp(command, clear) == 0)
return 'C';
}
char **set_arr(int number, char *command) {
static char **arr = NULL;
static int size;
switch (command_read(command)) {
case 'S':
size = (int)number;
arr = malloc((size + 1) * sizeof(char *));
for (int i = 0; i <= size; i++) {
arr[i] = NULL;
if (i == size)
break;
arr[i] = malloc((string_len) * sizeof(char));
}
break;
case 'C':
clear_arr(arr, size);
free(arr);
uintptr_t value = number;
uint64_t *temp = (void *)value;
*temp = 0x0;
break;
}
return arr;
}
void clear_arr(char *arr[], int size) {
for (int i = 0; i < size; i++) {
free(arr[i]);
arr[i] = NULL;
}
}
I know that there is better methods to clear (and allocate memory?) but my primary question is, did I free all the memory I allocated for the array, and after the clearing, does the pointer my_arr is set correctly to NULL?
Writing a generic function to achieve your goal is not possible in Standard C because pointers to different types of objects may have a different representation so you cannot pass the address of a pointer and expect the function to handle it in a generic manner.
Yet this provision in the C Standard is not used on most current systems today. In particular, the POSIX standard mandates that all pointers have the same representation. Hence your generic function can work on these systems, with some precautions to avoid compilation warnings:
// free an array of allocated things
void free_array(void ***p, size_t count) {
void **array = *p;
for (size_t i = 0; i < count; i++) {
free(array[i]);
array[i] = NULL; // for safety
}
free(array);
*p = NULL;
}
// deal with the non portable conversion with macros
#define FREE_ARRAY(p, n) free_array((void ***)(void *)&(p), n)
// allocate an array of pointers to allocated things of size `size`.
// return a pointer to the array or `NULL` if any allocation failed
void **malloc_array(size_t count, size_t size) {
void **array = malloc(count * sizeof(*array));
if (array) {
for (size_t i = 0; i < count; i++) {
array[i] = calloc(size, 1); // allocate and initialize to all bits zero
if (array[i] == NULL) {
while (i-- > 0) {
free(array[i]);
array[i] = NULL;
}
return NULL;
}
}
}
return array;
}
#define MALLOC_ARRAY(n, type) ((type **)(void *)malloc_array(n, sizeof(type)))
#define MALLOC_2D_ARRAY(n1, n2, type) ((type **)(void *)malloc_array(n1, (n2) * sizeof(type)))
Passing the command as a string is very inefficient. You should use an int or an enum for the command, but you can use the above macros and code in your program this way:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint-gcc.h>
int main() {
int string_len = 100;
int num = 10; // get number from user;
char **my_arr = MALLOC_2D_ARRAY(num, string_len, char);
FREE_ARRAY(my_arr, num);
return 0;
}
I am writing a program that takes integers as command line arguments. For each of these numbers I have to create a thread which calculates Fibonacci series up to that number. That function returns a struct pointer to the main where the data is printed.
Now, I have correctly done the fib calculations and checked them by printing the series within the function.
The problem arises when I try to return the struct pointer created within the thread function and use it to print the data in the main.
typedef struct thread_func_param
{
int *fib;
int size;
} thread_func_param;
//===================================================
void *fibGen(void *parameters)
{
int num = atoi(parameters);
struct thread_func_param *p;
p = malloc (sizeof (thread_func_param));
p->size = fibSize(num);
p->fib = malloc(sizeof(int)* p->size);
//Fibonacci Calculations
//..
//.
return (void *) p;
//pthread_exit((void *) p);
}
//===================================================
int main(int argc, char* argv[])
{
void* thread_result;
thread_func_param* p = malloc( sizeof(thread_func_param));
assert(argc > 1);
int noOfThreads = argc - 1;
printf("No of Thread = %d\n", noOfThreads);
pthread_t *threadID = malloc (sizeof (pthread_t) * noOfThreads);
pthread_attr_t attributes;
pthread_attr_init(&attributes);
int i, j;
for(i = 0; i < noOfThreads; i++)
{
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
pthread_join(threadID[i], thread_result);
//HOW TO USE THE RETURNED DATA?
for (j = 0; j< ((thread_func_param*)thread_result->size)-1; j++)
printf(" %d ", (thread_func_param*)thread_result->fib[j]);
}
return 0;
}
The solution that I use, in the end, to print the data gives error of dereferencing a void pointer (I am new with C). How can I correct it?
Two issues here:
pthread_join() takes a void** as 2nd parameter. The code passes a void* only.
To cast a pointer wrap it into parenthesis. Here the cast
(thread_func_param*)thread_result->size
refers to size not to thread_result. So what you want is
((thread_func_param*)thread_result)->size
However a nice and clean solution would only use a void pointer interimswise. It could look like this:
int main(int argc, char* argv[])
{
thread_func_param* thread_result;
...
...
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
{
void * pv;
pthread_join(threadID[i], &pv);
thread_result = pv;
}
if (NULL != thread_result) /* perform some sanity checking. */
{
for (j = 0; j < thread_result->size - 1; j++)
printf(" %d ", thread_result->fib[j]);
}
...
I have a task to create an array of pointers to structure. I need to use just void functions and "malloc". I have no idea how to do it, could you help me?
void create1(apteka*** a, int size)
{
**a = (apteka**) malloc(size* sizeof(apteka*));
for (int i = 0; i < size; i++)
{
x[0][i] = (apteka*)malloc(size * sizeof(apteka));
}
}
I have a task to create an array of pointers to structure
You need two "sizes":
The number of pointers
The size of the struct
You only pass one.
So fix your code for example like this
#include <stdlib.h> /* for malloc(), free() */
void create1(void *** pppv, size_t n, size_t s)
{
assert(NULL != pppv);
*pppv = malloc(n * sizeof **pppv);
if (NULL != *pppv)
{
for (size_t i = 0; i < n; ++i)
{
(*pppv)[i] = malloc(s);
if (NULL == (*pppv)[i])
{
/* Failed to completely allocate what has been requested,
so clean up */
for (--i; i >= 0; --i)
{
free((*pppv)[i]);
}
free(*pppv);
*pppv = NULL;
break;
}
}
}
}
Use it like this:
#include <stdlib.h> /* for size_t, free(), exit(), EXIT_FAILURE */
#include <stdio.h> /* for fputs() */
void create1(void ***, size_t, size_t);
struct my_struct
{
int i;
... /* more elements here */
}
#define N (42) /* Number of elements */
int main(void)
{
struct my_struct ** pps = NULL;
create1(&pps, N, sizeof **pps);
if (NULL == pps)
{
fputs(stderr, "create1() failed\n", stderr);
exit(EXIT_FAILURE);
}
/* use array pps[0..N]->i here */
/*Clean up */
for (size_t i = 0; i < N; --i)
{
free(pps[i]);
}
free(pps);
}
I was playing with double pointers in C and was wondering if I create a function that initializes the table, it crashes on going back to main when I try to make use of the memory allocated by InitStringTable. I believe a simple fix is to make strTable global and then I believe its OK, but I prefer not to do so as this is more of a learning exercise for me in passing the table around for modification i.e. I should be able to modify strTable from main or another function modifyTable after InitStringTable.
Thanks for any help you can give.
int main()
{
char** strTable;
// Allocates memory for string table.
InitStringTable(strTable);
// Below lines should be able to copy strings into newly allocated table.
// Below lines cause crash however.
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
// Allocates memory for the string table. This function should create a table
// of size 10 strings with each string 50 chars long. The code compiles fine.
void InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
}
C is pass by value.
The value assigned to table is lost on returning from InitStringTable().
Also when allocating pointers to char ask for room for pointers to char.
So this:
... = (char**)malloc(sizeof(char)*10);
shall at least be (assuming C):
... = malloc(sizeof(char*)*10);
A possible approach to this would be:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l)
{
int result = 0;
if (NULL == ppptable)
{
result = -1;
errno = EINVAL;
}
else
{
(*ppptable) = malloc(n * sizeof(**ppptable));
if (NULL == (*ppptable))
{
result = -1;
}
else
{
size_t i = 0;
for(; i < n; ++i)
{
(*ppptable)[i] = calloc(l, sizeof(*(*ppptable)[i]));
if (NULL == (*ppptable)[i])
{
result = -1;
/* Failing in the middle requires clean-up. */
for (; i > 0; --i)
{
free((*ppptable)[i-1]);
}
free(*ppptable);
(*ppptable) = NULL;
break;
}
}
}
}
return result;
}
Call it like this:
#include <stdlib.h>
#include <stdio.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l);
int main(void)
{
int result = EXIT_SUCCESS;
char ** strTable = NULL;
if ( -1 == InitStringTable(&strTable, 10, 42)) //* Allocate array with 10 "strings" à 42 chars. */
{
perror("InitStringTable() failed");
result = EXIT_FAILURE;
}
else
{
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
return result;
}
And no, I won't get into this ridiculous "You don't wanna be a 3-star-programmer!" discussion.
You have a pointer issue.
It's like if you say:
void inc(int a){
a++;
}
int main(){
int a = 0;
inc(a);
printf ("%d\n", a); // will display 0, not 1
}
does not work.
You must pass &strTable instead of strTable as InitStringTable argument, and change other things in InitStringTable consequently ..
Or just do strTable = InitStringTable(); , and return a char** from InitStringTable.
The lines below InitStringTable() crash, because they are trying to perform operations
on a memory address that is neither in the same scope as theirs nor have any reference to
that memory address.
The function InitStringTable() allocates memory to the table, but cannot be accessed by the
calling function (here main), because the memory is local to the function in which it
allocated.
Therefore in order to use the same memory address for operations in the
calling function you must pass a reference of that address to the calling function.
In your program you can do it as under :
Declare the function as :-
char **InitStringTable(char **);
int main()
{
char** strTable;
strTable = InitStringTable(strTable);
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
char **InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
/* after the function has finished its job, return the address of the table */
return table;
}
i got a problem with my C code.
int split(char* source, char*** target, char* splitChar) {
int i;
int currentLength;
int splitCharPosition;
char* currentSubstring = source;
int splitCount = charcount(source, splitChar) + 1;
*target = (char**) malloc(splitCount * sizeof(char**));
for(i=0;i<splitCount;i++) {
splitCharPosition = indexOf(currentSubstring, splitChar);
substring(currentSubstring, target[i], 0, splitCharPosition);
currentLength = strlen(currentSubstring);
substring(currentSubstring, ¤tSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
}
return splitCount;
}
The problem is that if I use the Debugger, the pointer to splitChar is set to 0x0 after the first run of the for loop.
Does anybody know why it is set to 0x0?
EDIT:
int indexOf(char* source, char* template) {
int i;
int j;
int index;
for (i = 0; source[i]; i++) {
index = i;
for (j = 0; template[j]; j++) {
if (source[i + j] != template[j]) {
index = -1;
break;
}
}
if (index != -1) {
return index;
}
}
return -1;
}
EDIT2:
int charcount(char* source, const char* countChar) {
int i;
int count = 0;
for(i=0;source[i];i++) {
if(source[i] == countChar[0]) {
count++;
}
}
return count;
}
EDIT3:
char* substring(char* source, char** target, int start, int length) {
*target = (char*) malloc(length + 1);
strncpy(*target, source + start, length);
target[length] = '\0';
return *target;
}
EDIT4:
I just noticed that if I add
char* sndfpgjps = splitChar;
to my split() code it does not delete the reference. Anyone know why?
This line:-
substring(currentSubstring, ¤tSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
... will cause a memory leak, as well as being incredibly inefficient. The old substring is left dangling. and never freed.
It would be much better to write
currentSubString += splitCharPosition + 1;
I don't think that's the problem, but it's a problem.
Also, as you're using C library functions like strlen(), why aren't you using strtok or better yet, strtok_r?
I have some reservations about the code, but this works cleanly under valgrind (no leaks, no abuse). I've left the sub-functions largely unchanged except that constant strings are marked constant. The code in split() has been simplified. As I noted in a comment, I suggest writing the main split() function so that you have a local char **string_list; which you allocate and fill. Then, when you're about to return, you assign *target = string_list;. This will make it easier for you to understand what's going on. Triple indirection is nasty. You can justify it here (just), but minimize the time you spend working with triple pointers. The revision adopts that strategy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int split(const char *source, char ***target, const char *splitStr);
static int
indexOf(const char *source, const char *template)
{
int i;
int j;
int index;
for (i = 0; source[i]; i++)
{
index = i;
for (j = 0; template[j]; j++)
{
if (source[i + j] != template[j])
{
index = -1;
break;
}
}
if (index != -1)
return index;
}
return -1;
}
static int
charcount(const char *source, const char *countChar)
{
int count = 0;
for (int i = 0; source[i]; i++)
{
if (source[i] == countChar[0])
count++;
}
return count;
}
static char *
substring(const char *source, int start, int length)
{
char *target = (char *)malloc(length + 1);
if (target != 0)
{
memmove(target, source + start, length);
target[length] = '\0';
}
return target;
}
int
split(const char *source, char ***target, const char *splitStr)
{
int splitCount = charcount(source, splitStr) + 1;
char **result = (char **)malloc(splitCount * sizeof(*result));
if (result == 0)
return -1;
int splitLength = strlen(splitStr);
char **next = result;
const char *currentSubstring = source;
for (int i = 0; i < splitCount; i++)
{
int splitCharPosition = indexOf(currentSubstring, splitStr);
if (splitCharPosition < 0)
break;
*next++ = substring(currentSubstring, 0, splitCharPosition);
currentSubstring += splitCharPosition + splitLength;
}
*next++ = substring(currentSubstring, 0, strlen(currentSubstring));
*target = result;
return (next - result); /* Actual number of strings */
}
static void print_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
{
if (strings[i] != 0)
printf("%d: <<%s>>\n", i, strings[i]);
}
}
static void free_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
free(strings[i]);
free(strings);
}
int main(void)
{
const char source[] = "This is a string; it is really!";
char **strings;
int nstrings;
nstrings = split(source, &strings, " ");
printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
print_list(nstrings, strings);
free_list(nstrings, strings);
nstrings = split(source, &strings, "is");
printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
print_list(nstrings, strings);
free_list(nstrings, strings);
return 0;
}
Note that in the second example, charcount() returns 6 but there are only 4 strings. This caused a late adjustment to the source code. (You could realloc() the result so it is exactly the right size, but it probably isn't worth worrying about unless the discrepancy is really marked — say 'more than 10 entries'.) The error handling is not perfect; it doesn't access invalid memory after failure to allocate, but it doesn't stop trying to allocate, either. Nor does it report failures to allocate individual strings — it does for failure to allocate the array of pointers.
I'd probably avoid the triple pointer by creating a structure:
typedef struct StringList
{
size_t nstrings;
char **strings;
} StringList;
You can then pass a pointer to one of these into split(), and into the utility functions such as free_list() and print_list(). The free_list() function would then modify the structure so that both elements are zeroed after the data pointed at by the structure is freed.
I'd also be tempted to use a different implementation of indexOf():
int indexOf(const char *haystack, const char *needle)
{
const char *pos = strstr(haystack, needle);
if (pos != 0)
return (pos - haystack);
return -1;
}
I do not know what substring does, nor what signature it has, but in the line
substring(currentSubstring, target[i], 0, splitCharPosition);
target[i] is only defined for i==0. I believe you wanted to write
substring(currentSubstring, (*target)[i], 0, splitCharPosition);
See if your debugger also supports data breakpoints, i.e. break if some place in memory is modified. Then place one at the actual address of splitChar, and another at the address it points to. (Since you didn't specify whether the pointer is null or points to nil.) See where it breaks. It may be that it is a completely unrelated place; that would indicate a buffer overflow.
Also, you could make at least splitChar a pointer to const. You don't actually want to modify it, right? Better idea, make it a char, not a pointer, since its name suggests that there is only one character on which you split, not a string.
The first call to substring does not look correct:
substring(currentSubstring, target[i], 0, splitCharPosition);
I suspect it should be something like the following where it indexes the actual memory that was allocated:
substring(currentSubstring, &((*target)[i]), 0, splitCharPosition);
You first need to get the value that target points at (*target) and then index off of that and pass the address of that array location.