Why do I get segmentation fault when executing the following piece of code? I noticed that if I declare a second stack ( char s2[10000]; and init_context2(&unew2, s2, 10000);) everything works fine. But I can't understand why two stacks are required. Is it possible to use only one, if yes how?
output:
before context init
before context swap
Message
Message2
Segmentation fault
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
ucontext_t uold, unew, unew2;
char s1[10000];
static void message()
{
puts("Message");
}
static void message2()
{
puts("Message2");
}
void init_context(ucontext_t * uc, void* stack, size_t stack_size)
{
//puts("Inside init context");
getcontext(uc);
uc->uc_link = &uold;
uc->uc_stack.ss_sp = stack;
uc->uc_stack.ss_size = stack_size;
uc->uc_stack.ss_flags = 0;
makecontext(uc, message, 0);
}
void init_context2(ucontext_t * uc, void* stack, size_t stack_size)
{
//puts("Inside init context 2");
getcontext(uc);
uc->uc_link = &uold;
uc->uc_stack.ss_sp = stack;
uc->uc_stack.ss_size = stack_size;
uc->uc_stack.ss_flags = 0;
makecontext(uc, message2, 0);
}
int main(int argc, char** argv) {
int i;
for(i=0; i<10; i++)
{
puts("before context init");
init_context(&unew, s1, 10000);
init_context2(&unew2, s1, 10000);
puts("before context swap");
swapcontext(&uold, &unew);
swapcontext(&uold, &unew2);
}
return (EXIT_SUCCESS);
}
The reason is that you are reusing the stack simultaneously for both contexts; that is, while both contexts are valid. makecontext initializes the stack with something (not sure exactly what, but possibly a return address that links back to the previous context), and thus one clobbers the other.
Simple moving your call to init_context2() to after the first context has run makes the program work:
for(i=0; i<10; i++)
{
puts("before context init");
init_context(&unew, s1, 10000);
puts("before context swap");
swapcontext(&uold, &unew);
init_context2(&unew2, s1, 10000);
swapcontext(&uold, &unew2);
}
Related
I am trying to fill a stack (reserved by malloc) with the value 0xAA or 0b10101010. I think I manage to fill the stack, but printing it, I get different outputs (e83e83e83... or 41f41f41f... for example) depending on my stacksize.
Does anyone have an idea how to solve the problem?
int main(void) {
int status;
int stacksize = 1000;
void* stack=malloc(stacksize);
void* stackTop = stack + stacksize;
for(int i =0; i<stacksize;i++){
stackTop = "10101010";
stackTop --;
}
stackTop =stack + stacksize;
for(int i =0; i<stacksize;i++){
printf("%x", stacksize);
}
return 0;
}
It's somewhat hard to understand from your code and comments, what you're actually trying to do. But if I were to extrapolate on it, you're trying to create a "stack", with an element size of a byte. Here's a quick-and-dirty implementation of such a stack, with bounds checking:
#include <stdio.h>
#include <string.h>
#define STACK_SIZE 1000
struct stack {
int top;
unsigned char elts[STACK_SIZE];
};
static void stack_push(struct stack *s, unsigned char elt) {
if (s->top < STACK_SIZE-1) {
s->elts[s->top++] = elt;
} else {
// No space left in the stack.
}
}
static void stack_pop(struct stack *s) {
if (s->top) {
s->top--;
} else {
// Stack is empty
}
}
static void stack_fill(struct stack *s, unsigned char v) {
memset(s->elts, v, STACK_SIZE);
s->top = STACK_SIZE-1;
}
int main(void) {
// Example driver
struct stack s;
stack_fill(&s, 0xAA);
for (int i = 0; i < STACK_SIZE; i++) {
printf("%d: %02x\n", s.elts[s.top]);
stack_pop(&s);
}
return 0;
}
As an improvement, you could consider e.g. having stack_pop return the popped element, or return some kind of an error if the stack is empty. Or a peek function which returns the top, or an error similar to the one earlier described. However, I omitted them for brevity.
EDIT: To initialize the stack, the only thing required is to set the top member to 0. Initialization function (if needed) is thus trivial to write.
You are filling the stack with strings of chars and reading pointers to them.
The answer given by Paul Hankin in the comment states one of the correct solutions that is using
memset(stack, 0xAA, stacksize);
to fill your stack
thus producing the following code
int main()
{
int status;
int stacksize = 1000;
void* stack = malloc(stacksize);
void* stackTop = stack + stacksize;
memset(stack, 0xAA, stacksize);
for(int i =0; i < stacksize;i++){
printf("%x\n", ((unsigned char*)stack)[i]);
}
return 0;
}
My code is not working... But another example that is similar to my code is working. How can I fix?
It seems like pthread_join() is internally change integer value like my code. But mine does not work.
Can anybody help me to fix?
#include <stdio.h>
void test(void **temp) {
int foo = 3;
*temp = foo;
}
int main(void) {
int temp;
test((void **)&temp);
printf("%d\n", temp);
return 0;
}
pthread_join example:
#include <pthread.h>
#include <stdlib.h>
void *test(void *data) {
int i;
int a = *(int *)data;
for (i = 0; i < 10; i++) {
printf("%d\n", i * a);
}
}
int main() {
int a = 100;
pthread_t thread_t;
int status;
if (pthread_create(&thread_t, NULL, test, (void *)&a) < 0) {
perror("thread create error:");
exit(0);
}
pthread_join(thread_t, (void **)&status);
printf("Thread End %d\n", status);
return 1;
}
But mine does not work..
This statement:
pthread_join(thread_t, (void **)&status);
assigns to status the return value of your thread function. But your function doesn't return anything, so you get garbage.
To fix this, make your test function return something.
P.S. Please do turn on compiler warnings (-Wall, -Wextra) -- the compiler should have warned you of the bug already.
P.P.S Please do not name your variables like this: thread_t -- the _t stands for type, and thead_t is not a type.
You are trying to make temp into two void pointers (void**) when you actually only have one pointer to the int temp. Just return the pointer value and you can use this in a similar pthread example.
#include <stdio.h>
#include <stdlib.h>
void *test(void *temp) {
int *ptr = (int*)malloc(sizeof(int));
*ptr = 3;
return ptr;
}
int main(int argc, char *argv[]) {
int *temp = (int*)test(nullptr);
printf("%d\n", *temp);
free(temp);
return 0;
}
The trampoline function in the program below works properly. I think the program below results in stack overflow because the functions thunk_f and thunk1 call each other indefinitely, resulting in the creation of new stack frames. However, I want to write a program that behaves more similarly to a nonterminating loop, as trampolines should prevent stack overflow.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
void trampoline(void *(*func)()) {
while (func) {
void *call = func();
func = (void *(*)())call;
}
}
void *thunk1(int *param);
void *thunk_f(int *param);
void *thunk1(int *param)
{
++*param;
trampoline(thunk_f(param));
return NULL;
}
void *thunk_f(int *param)
{
return thunk1(param);
}
int main(int argc, char **argv)
{
int a = 4;
trampoline(thunk1(&a));
printf("%d\n", a);
}
You are using the trampoline incorrectly: rather than letting it invoke your thunk_f function, you call it with the result of the thunk_f function.
As a result, you are getting a stack overflow. You can avoid the stack overflow (but not the infinite loop) by returning thunk_f instead of calling it:
void *thunk1(int *param)
{
++*param;
return thunk_f;
}
And calling trampoline in main correctly:
int main(int argc, char **argv)
{
int a = 4;
trampoline(thunk1, &a);
printf("%d\n", a);
}
And of course this requires that trampoline gets an additional argument, to pass the &a parameter on:
void trampoline(void *(*func)(int *), int *arg) {
while (func) {
void *call = func(arg);
func = (void *(*)())call;
}
}
This works — but as noted, it’s just an infinite loop without output. To see what’s happening, put the printf inside thunk1:
void *thunk1(int *param)
{
printf("%d\n", ++*param);
return thunk_f;
}
Lastly, I should probably note that this is invalid C, because it’s illegal to convert between a object pointer and a function pointer (always compile with pedantic warnings!). To make the code legal, wrap the function pointer into an object:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct f {
struct f (*p)(void *);
};
void trampoline(struct f f, void *args) {
while (f.p) {
f = (f.p)(args);
}
}
struct f thunk1(void *param);
struct f thunk_f(void *param);
struct f thunk1(void *param) {
printf("%d\n", ++*((int *) param));
return (struct f) {thunk_f};
}
struct f thunk_f(void *param) {
return thunk1(param);
}
int main() {
int a = 4;
trampoline((struct f) {thunk1}, &a);
}
I'm trying to pass pointers to struct lower_hyper_id from a thread to the main thread, by the means of pthread_exit() function, that would compare and output the value in the struct. However, i receive an error (Segmentation fault) when i am trying to use the returned value and cast it to the struct.
thread that creates and returns the struct:
void *compute(void *arg){
lower_hyper_id *data = (lower_hyper_id *)malloc(sizeof(lower_hyper_id));
//some code
//i debug the program, and at this point, the struct i want
//to return has the values i want.
pthread_exit((void *)data);
}
in the main:
lower_hyper_id l_hyper_id;
int main(){
void *ap_state;
lower_hyper_id values;
void *ret;
//some code
for (int i = 0; i < NUMBER_OF_FILTERING_THREADS; i++)
{
s = pthread_join(filtering_threads[i], (void *)&ret);
//some error checking
values = *((lower_hyper_id *)ret); //this is where i receive the error
if (values.lowest_cost <= l_hyper_id.lowest_cost)
{
l_hyper_id.hyper_id = values.hyper_id;
l_hyper_id.lowest_cost = values.lowest_cost;
}
free(ret);
}
I have already looked at answers in the stackoverflow such as this question, but it hasn't helped me resolving this. I actually changed the code to be exactly equal to the code in this answer, but still it gives me an error.
You're not testing if malloc returned NULL. That could be an issue if you're allocing a large chunk and the allocation can fail.
Other than that, I don't think the problem is in the return value passing.
pthread_exit()ing with a mallocd pointer should work just fine.
A minimial working example:
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *compute (void *arg)
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
size_t sz = strlen("hello world")+1;
char *ret = malloc(sz+1);
if(ret) memcpy(ret, "hello world", sz+1);
return ret;
}
int main()
{
printf("thread=%llx\n", (unsigned long long)pthread_self());
pthread_t ptid;
int er;
if((er=pthread_create(&ptid,0,compute,0))) return errno=er,perror(0),1;
void *retval;
if((er=pthread_join(ptid,&retval))) return errno=er,perror(0),1;
printf("thread returned: %s\n", (char*)retval);
free(retval);
}
How do you create a function pointer with struct table such as
static struct {
int pid;
int queue[MAXPROCS];
} semtab[MAXSEMS];
I think I understand how to make OO equivalent in C using function pointer with this post, but how can I do with when my struct is an array. I'm still a little iffy with the syntax.
Would it be something like
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int) = enqueue;
// or is it void(*enqueue)(semtable[]*) ?
int (*fcnPtr_dequeue)() = dequeue;
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
// then to use it, it would be like this?
void foo() {
semtab[5].enqueue(6);
}
Use
static struct {
int pid;
int queue[MAXPROCS];
void (*fncPtr_enqueue)(int); // This defines a member fncPtr_enqueue
int (*fncPtr_dequeue)(); // Note that you had fcnPtr_ in your post.
// I have fncPtr_ here.
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue() { /* code */ }
Each object in semtab that needs to have valid function pointers needs to be updated.
semtab[0].fncPtr_enqueue = enqueue;
semtab[0].fncPtr_dequeue = dequeue;
You could use:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS];
void enqueue(int i) { /* code */ }
int dequeue(void) { /* code */ }
void foo(void)
{
semtab[5].enqueue(6);
}
Changes include:
Systematic names for structure member pointers (instead of mixed fncPtr and fcnPtr prefixes).
No attempt to initialize in the structure definition.
Add void to function prototypes to indicate no arguments. In C (and in contrast to C++), an empty pair of brackets (parentheses) means "a function taking an undefined number of arguments, but not one which has a variable argument list with ... ellipsis".
Because of (1), the original invocation is OK. (With the original code, you'd have needed semtab[5].fncPtr_enqueue(6); — or even (*semtab[5].fncPtr_enqueue)(6);)
You would still have to ensure that the function pointers in the table are all initialized.
With GCC and C99 or C11 compilation, you could initialize the array using:
static struct
{
int pid;
int queue[MAXPROCS];
void (*enqueue)(int);
int (*dequeue)(void);
} semtab[MAXSEMS] =
{
[0 ... MAXSEMS-1] = { .enqueue = enqueue, .dequeue = dequeue }
};
The [0 ... MAXSEMS-1] part is a GCC extension. Observe that a space is required after the 0 to avoid problems with the 'maximal munch' rule.
As JS1 mentioned in the comments, it's actually pretty pointless to do this with the example you have, as you're not achieving anything with the indirection if you're not going to vary the value of those pointers.
That being said, here's an example using a stack (because the logic is easier than a queue, and this is a simple example). Note that you must pass a pointer to the stack to each of your member functions, because while C++ member functions have an implicit this argument, C functions never do. You also need to give your struct a name, otherwise you won't be able to refer to it in the abstract, which you need to do.
This program uses the same struct to implement two variations of a stack, one normal one, and one which unnecessarily shouts at you when you push or pop:
#include <stdio.h>
#include <stdlib.h>
enum {
STACKSIZE = 1024
};
struct stack {
int stack[STACKSIZE];
size_t top;
void (*push)(struct stack *, int);
int (*pop)(struct stack *);
void (*destroy)(struct stack *);
};
void stack_push(struct stack * this, int i)
{
if ( this->top == STACKSIZE ) {
fprintf(stderr, "Queue full!\n");
exit(EXIT_FAILURE);
}
this->stack[this->top++] = i;
}
void stack_push_verbose(struct stack * this, int i)
{
stack_push(this, i);
printf("** PUSHING %d ONTO STACK! **\n", i);
}
int stack_pop(struct stack * this)
{
if ( this->top == 0 ) {
fprintf(stderr, "Stack empty!\n");
exit(EXIT_FAILURE);
}
return this->stack[--this->top];
}
int stack_pop_verbose(struct stack * this)
{
const int n = stack_pop(this);
printf("** POPPING %d FROM STACK! **\n", n);
return n;
}
void stack_destroy(struct stack * this)
{
free(this);
}
struct stack * stack_create(void)
{
struct stack * new_stack = malloc(sizeof * new_stack);
if ( !new_stack ) {
perror("Couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
new_stack->push = stack_push;
new_stack->pop = stack_pop;
new_stack->destroy = stack_destroy;
return new_stack;
}
struct stack * stack_verbose_create(void)
{
struct stack * new_stack = stack_create();
new_stack->push = stack_push_verbose;
new_stack->pop = stack_pop_verbose;
return new_stack;
}
int main(void)
{
struct stack * stack1 = stack_create();
struct stack * stack2 = stack_verbose_create();
stack1->push(stack1, 4);
stack1->push(stack1, 3);
stack1->push(stack1, 2);
printf("Popped from stack1: %d\n", stack1->pop(stack1));
stack2->push(stack2, 5);
stack2->push(stack2, 6);
printf("Popped from stack2: %d\n", stack2->pop(stack2));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack2: %d\n", stack2->pop(stack2));
stack1->destroy(stack1);
stack2->destroy(stack2);
return 0;
}
with output:
paul#horus:~/src/sandbox$ ./stack
Popped from stack1: 2
** PUSHING 5 ONTO STACK! **
** PUSHING 6 ONTO STACK! **
** POPPING 6 FROM STACK! **
Popped from stack2: 6
Popped from stack1: 3
Popped from stack1: 4
** POPPING 5 FROM STACK! **
Popped from stack2: 5
paul#horus:~/src/sandbox$
Note that we use the exact same struct stack for both types of stack - the differences between them are implemented by having the function pointers point to different functions in each case. The only visible difference to the user is that one is created with stack_create(), and the other is created with stack_create_verbose(). In all other respects, they're used identically, so you can see the polymorphism at work.