I have simplified my source like the following :
void *thread1(void *param)
{
pthread_detach(pthread_self());
while(1)
{
sleep( 3 ) ;
printf("hello world in thread1 \n");
} //while
return NULL ;
} //thread1
int main()
{
pthread_t tid ;
pthread_create(&tid , NULL, thread1, (void*)3);
while(1)
{
sleep( 3 ) ;
printf("hello world in main \n");
} //while
} // main
and compile it by :
g++ --std=c++11 -fprofile-generate xxx.cpp -pthread -o xxx.exe
in g++ 4.8.5 , execute xxx.exe can not see xxx.gcda , and then I simplified
it to the following ..... only main thread !!
int main()
{
while(1)
{
sleep( 3 ) ;
printf("hello world in main \n");
} //while
} // main
and compiled by :
g++ --std=c++11 -fprofile-generate yyy.cpp -o yyy.exe
in the same compiler g++ 4.8.5 and execute , still no yyy.gcda created !!
In a simple case like above , What I missed so no gcda been created ?!
Related
I have a pthreads based program with 3 threads that crashes on MacOS (Darwin Kernel Version 19.6.0) within a few seconds. I was expecting the same behavior on Linux. But the program doesn't crash on Linux. I am left speculating if Linux has a different thread scheduling policy or if it is something else. Any pointers appreciated.
This is the program. If I don't use pthread mutex lock in the printer thread, it is supposed to crash because the linked list is left in an inconsistent state.
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include "list.h"
#define RANGE_MIN 1
#define RANGE_MAX 10
pthread_t tid[3];
list_t list;
pthread_mutex_t queue_lock;
/* Return a uniformly random number in the range [low,high]. */
int random_range (unsigned const low, unsigned const high)
{
unsigned const range = high - low + 1;
return low + (int) (((double) range) * rand() / (RAND_MAX + 1.0));
}
/*
* consumer thread function
*/
void* consumer(void *arg)
{
static int val = 0;
while (1) {
//sleep(1);
pthread_mutex_lock(&queue_lock);
while (list.total_elem > 0)
consume_and_delete(&list);
pthread_mutex_unlock(&queue_lock);
}
}
void *producer(void *arg)
{
while (1) {
//sleep(1);
pthread_mutex_lock(&queue_lock);
while (list.total_elem < 10)
add_to_list(&list, random_range(RANGE_MIN, RANGE_MAX));
pthread_mutex_unlock(&queue_lock);
}
}
/*
* printer thread function
*/
void* printer(void *arg)
{
while (1) {
//pthread_mutex_lock(&queue_lock); //lines deliberately commented out to show the crash
print_list(&list);
//pthread_mutex_unlock(&queue_lock);
}
}
int main(void)
{
int ret;
if (pthread_mutex_init(&queue_lock, NULL) != 0) {
printf("\n mutex init failed\n");
return 1;
}
ret = pthread_create(&(tid[1]), NULL, &consumer, NULL);
if (ret != 0) {
printf("\ncan't create thread :[%s]", strerror(ret));
}
ret = pthread_create(&(tid[0]), NULL, &producer, NULL);
if (ret != 0) {
printf("\ncan't create thread :[%s]", strerror(ret));
}
ret = pthread_create(&(tid[2]), NULL, &printer, NULL);
if (ret != 0) {
printf("\ncan't create thread :[%s]", strerror(ret));
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_join(tid[2], NULL);
pthread_mutex_destroy(&queue_lock);
return 0;
}
For the sake of completeness, here is the code for list.h and list.c
ifndef __LIST_H__
#define __LIST_H__
typedef struct node_ {
int num;
struct node_ *next;
} node_t;
typedef struct list_ {
int total_elem;
node_t *head;
} list_t;
#define TRUE 1
#define FALSE 0
void add_to_list(list_t *list, int num);
node_t *allocate_new(int num);
void consume_and_delete(list_t *list);
void print_list(list_t *list);
#endif
list.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
void add_to_list(list_t *list, int val)
{
node_t *tmp;
node_t *new;
new = allocate_new(val);
if (!new) {
printf("%s: allocation failure \n", __FUNCTION__);
}
printf("%s: Enqueueing %d\n", __FUNCTION__, new->num);
if (!list) {
return;
}
if (!list->head) {
list->total_elem++;
list->head = new;
return;
}
tmp = list->head;
while (tmp->next) {
tmp = tmp->next;
}
tmp->next = new;
list->total_elem++;
}
node_t *allocate_new(int num)
{
node_t *tmp;
tmp = malloc(sizeof(node_t));
if (!tmp) {
printf("%s: failed in malloc\n", __FUNCTION__);
return NULL;
}
tmp->num = num;
tmp->next = NULL;
return tmp;
}
/* reads from the front of the queue and deletes the element
*/
void consume_and_delete(list_t *list)
{
node_t *tmp, *next;
if (!list->head) {
return;
}
tmp = list->head;
next = tmp->next;
printf("%s: Dequeueing %d\n", __FUNCTION__,tmp->num);
list->head = next;
list->total_elem--;
free(tmp);
}
void print_list(list_t *list)
{
node_t *tmp;
if (!list->head) {
printf("%s: queue empty \n", __FUNCTION__);
}
tmp = list->head;
while (tmp) {
printf("%d ", tmp->num);
tmp = tmp->next;
}
printf("\n");
}
Makefile:
all: prodcon
prodcon: list.o prod_consume.o
gcc -g -o prodcon list.o prod_consume.o -lpthread
list.o: list.c list.h
gcc -g -c -o list.o list.c
prod_consume.o: prod_consume.c list.h
gcc -g -c -o prod_consume.o prod_consume.c
clean:
rm -f *.o ./prodcon
Note that if I un-comment pthread_mutex_lock and unlock calls in printer fn, the program runs without a crash on MacOS, as expected. But on Linux, even without un-commenting those lines in printer thread, it runs fine.
So my question. Is thread scheduling different in Linux. Or is is there some other reason?
Any reason the program runs fine on Linux, while it crahes on MacOS?
//lines deliberately commented out to show the crash
The print_list accesses the list without the lock; of course the code will intermittently crash, what did you expect?
on Linux, even without un-commenting those lines in printer thread, it runs fine.
It doesn't "run fine" -- it exercises undefined behavior, and will crash if you run enough times and the stars align to expose the data race.
I face one issue in my customized malloc().
My software
First of all, let me explain my software:
My software is huge and is composed of multiple static libraries. As one of static libraries has the customized malloc(), whose main function is a sort of proprietary memory tracer on the top of calling mall() from glibc. Currently the customized malloc() is available only some applications but not all applications in my system. My aim is to link the customized malloc() to every application running on my system. In my previous post, I asked why there was 'undefined sysmbol' shown during the run time even though I used the flag of LTLD_LAZY. It turned out the my code was not correct. So I fixed my code. And the issue is resolved. But still I have an issue. Let me explain my code first.
cat common.c
#include <stdio.h>
#include <stdlib.h>
void *gp_malloc(size_t size) {
void *ptr;
ptr = malloc(size);
fprintf(stderr, "%s: size(%d) = %p\n", __func__, (int)size, ptr);
return ptr;
}
void gp_free(void *ptr) {
free(ptr);
fprintf(stderr, "%s free=%p\n", __func__, ptr);
}
cat my_malloc.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <malloc.h>
static void *handle = NULL;
static void *(*gp_malloc)(size_t size) = NULL;
static void (*gp_free)(void *ptr) = NULL;
void *my_malloc(size_t size) {
char *error;
void *ptr;
/* dynamically load the shared lib that contains gp_malloc() */
if (gp_malloc == NULL) {
handle = dlopen("./libcommon.so", RTLD_LAZY| RTLD_GLOBAL);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
return NULL;
}
/* get a pointer to the gp_malloc() function we just loaded */
gp_malloc = dlsym(handle, "gp_malloc");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return NULL;
}
}
/* Now we can call gp_malloc() just like any other function */
fprintf(stderr, "%s size=%ld\n", __func__, size);
ptr = gp_malloc(size);
return ptr;
}
void my_free(void *ptr) {
char *error;
//void *ptr;
/* dynamically load the shared lib that contains gp_malloc() */
if (gp_free == NULL) {
gp_free = dlsym(handle, "gp_malloc");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
return;
}
}
/* Now we can call gp_malloc() just like any other function */
fprintf(stderr, "%s: start %p\n", __func__, ptr);
gp_free(ptr);
}
void bbb(void) {
extern void aaa(void);
aaa();
}
cat hello_exits.c
#include <stdio.h>
#include <stdlib.h>
extern void *gp_malloc(int);
extern void gp_free(void *);
int main(void) {
char *ptr;
ptr = gp_malloc(10);
gp_free(ptr);
exit(0);
}
cat hello_new.c
#include <stdio.h>
#include <stdlib.h>
#include "my_malloc.h"
int main(void) {
char *ptr;
ptr = malloc(10);
free(ptr);
}
cat my_static.c
#include <stdio.h>
void aaa(void) {
printf("I am in aaa\n");
}
cat my_malloc.h
#ifdef COMPILE_TIME_MY_MALLOC
#define malloc(size) my_malloc(size)
#define free(ptr) my_free(ptr)
void *my_malloc(size_t size);
void my_free(void *ptr);
#endif
cat Makefile_new
LOCAL_PATH=${shell pwd}
all:
gcc -c -Wall -fPIC -o my_malloc.o -c my_malloc.c
gcc -O2 -Wall -shared -fPIC -o libmy_malloc.so my_malloc.o
# This shared library is built with Makefile_exist
# gcc -O2 -Wall -shared -fPIC -o libcommon.so common.c
gcc -L${LOCAL_PATH} -g -Wall -D COMPILE_TIME_MY_MALLOC -o hello_new hello_new.c -lmy_malloc -ldl
cat Makefile_exist
LOCAL_PATH=${shell pwd}
all:
gcc -c -Wall -o my_static.o -c my_static.c
ar -rc libmy_static.a my_static.o
gcc -O2 -Wall -shared -fPIC -o libcommon.so common.c
gcc -L${LOCAL_PATH} -g -Wall -o hello_exist hello_exist.c -lcommon -lmy_static -ldl
In order to build the image, run Makefile_exist, Makefile_new sequentially so that hello_new is created. (Makefile_exist/Makefile_new is a simplified version of my makefiles. The former is one that I use. The later is one that I am going to apply to other applications)
When I run hello_new, I got gp_malloc twice. I understand the 1st one. What causes the 2nd gp_malloc()?
./hello_new
my_malloc size=10
gp_malloc: size(10) = 0x7fffe0d5b900
my_free: start 0x7fffe0d5b900
gp_malloc: size(-522864384) = (nil) //what causes this to be called.
Any suggestion will be highly appreciated.
I am creating simple XPCOM plugin for firefox by using the code from.
blog.peschla.net code is straight forward but Im getting following error:
Error 1 error MSB3073: The command "xpidl-build.bat IHelloWorld.idl
:VCEnd" exited with code 1. C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets 103 6 HelloWorld
I am using firefox 22 hence gecko-sdk version 22 and vs2010
I used following files.
I have given link above which contains all the code but I am giving code below as well
1)HelloWorld.h
#include "HelloWorld.h"
NS_IMPL_ISUPPORTS1(HelloWorld, IHelloWorld)
HelloWorld::HelloWorld()
{
mName.Assign(L"Nameless");
}
HelloWorld::~HelloWorld(){}
/* attribute AString name; */
NS_IMETHODIMP HelloWorld::GetName(nsAString & aName)
{
aName.Assign(mName);
return NS_OK;
}
NS_IMETHODIMP HelloWorld::SetName(const nsAString & aName)
{
mName.Assign(aName);
return NS_OK;
}
/* long add (in long a, in long b); */
NS_IMETHODIMP HelloWorld::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval NS_OUTPARAM)
{
*_retval = a + b;
return NS_OK;
}
2)HelloWorld.cpp
#include "HelloWorld.h"
NS_IMPL_ISUPPORTS1(HelloWorld, IHelloWorld)
HelloWorld::HelloWorld()
{
mName.Assign(L"Nameless");
}
HelloWorld::~HelloWorld(){}
/* attribute AString name; */
NS_IMETHODIMP HelloWorld::GetName(nsAString & aName)
{
aName.Assign(mName);
return NS_OK;
}
NS_IMETHODIMP HelloWorld::SetName(const nsAString & aName)
{
mName.Assign(aName);
return NS_OK;
}
/* long add (in long a, in long b); */
NS_IMETHODIMP HelloWorld::Add(PRInt32 a, PRInt32 b, PRInt32 *_retval NS_OUTPARAM)
{
*_retval = a + b;
return NS_OK;
}
3)IHelloWorld.idl
#include "nsISupports.idl"
[scriptable, uuid(2f52e0f0-0eac-11e1-be50-0800200c9a66)]
interface IHelloWorld : nsISupports
{
attribute AString name;
long add(in long a, in long b);
}
4)HelloWorldModule.cpp
#include "mozilla/ModuleUtils.h"
#include "nsIClassInfoImpl.h"
#include "HelloWorld.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(HelloWorld)
// The following line defines a kHELLOWORLD_CID CID variable.
NS_DEFINE_NAMED_CID(HELLOWORLD_CID);
static const mozilla::Module::CIDEntry kSampleCIDs[] = {
{ &kHELLOWORLD_CID, false, NULL, HelloWorldConstructor },
{ NULL }
};
static const mozilla::Module::ContractIDEntry kSampleContracts[] = {
{ HELLOWORLD_CONTRACTID, &kHELLOWORLD_CID },
{ NULL }
};
static const mozilla::Module kSampleModule = {
mozilla::Module::kVersion,
kSampleCIDs,
kSampleContracts,
NULL /* or a category definition if you need it */
};
NSMODULE_DEFN(nsSampleModule) = &kSampleModule;
5)xpidl-build.bat (using as Command Line call to the Pre-Build Event)
..\..\xulrunner-sdk\sdk\bin\xpidl.exe -m header -I..\..\xulrunner-sdk\idl %1
..\..\xulrunner-sdk\sdk\bin\xpidl.exe -m typelib -I..\..\xulrunner-sdk\idl %1
I found my mistake.Reason for error: "I was putting gecko-sdk in wrong directory".Now my project is able to build.
Thanks to all who had replied for this thread.
I just want to resume the func coroutine twice, yield if n==0, and return if n==1 , but it core dumps, what't wrong with it?
the "hello world" should always be left in LL's stack, I can't figure out what is wrong.
[liangdong#cq01-clientbe-code00.vm.baidu.com lua]$ ./main
func_top=1 top=hello world
first_top=1 top_string=hello world
Segmentation fault (core dumped)
[liangdong#cq01-clientbe-code00.vm.baidu.com lua]$ cat main.c
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int n = 0;
int func(lua_State *L) {
printf("func_top=%d top=%s\n", lua_gettop(L), lua_tostring(L, -1));
if (!n) {
++ n;
return lua_yield(L, 1);
} else {
return 1;
}
}
int main(int argc, char* const argv[]) {
lua_State *L = luaL_newstate();
/* init lua library */
lua_pushcfunction(L, luaopen_base);
if (lua_pcall(L, 0, 0, 0) != 0) {
return 1;
}
lua_pushcfunction(L, luaopen_package);
if (lua_pcall(L, 0, 0, 0 ) != 0) {
return 2;
}
/* create the coroutine */
lua_State *LL = lua_newthread(L);
lua_pushcfunction(LL, func);
lua_pushstring(LL, "hello world");
/* first time resume */
if (lua_resume(LL, 1) == LUA_YIELD) {
printf("first_top=%d top_string=%s\n", lua_gettop(LL), lua_tostring(LL, -1));
/* twice resume */
if (lua_resume(LL, 1) == 0) {
printf("second_top=%d top_string=%s\n", lua_gettop(LL), lua_tostring(LL, -1));
}
}
lua_close(L);
return 0;
}
it core dumps in lua5.1, but works well in lua5.2 if change lua_resume(LL, 1) to lua_resume(LL, NULL, 1).
EDIT: I was actually totally wrong.
You cannot resume a C function.
I'm trying to present to the screen an error output when the user enters an incomplete
define , e.g :
#define A // this is wrong , error message should appear
#define A 5 // this is the correct form , no error message would be presented
but it doesn't work , here's the code :
%{
#include <stdio.h>
#include <string.h>
%}
%s FULLCOMMENT
%s LINECOMMENT
%s DEFINE
%s INCLUDE
%s PRINT
%s PSEUDO_C_CODE
STRING [^ \n]*
%%
<FULLCOMMENT>"*/" { BEGIN INITIAL; }
<FULLCOMMENT>. { /* Do Nothing */ }
<INCLUDE>"<stdio.h>"|"<stdlib.h>"|"<string.h>" { BEGIN INITIAL; }
<INCLUDE>. { printf("error\n"); return 0 ; }
<DEFINE>[ \t] { printf("eat a space within define\n"); }
<DEFINE>{STRING} { printf("eat string %s\n" , yytext);}
<DEFINE>\n { printf("eat a break line within define\n"); BEGIN INITIAL; }
"#include" { BEGIN INCLUDE; }
"#define" { printf("you gonna to define\n"); BEGIN DEFINE; }
"#define"+. { printf("error\n"); }
%%
int yywrap(void) { return 1; } // Callback at end of file
int main(void) {
yylex();
return 0 ;
}
Where did I go wrong ?
Here is the output :
a#ubuntu:~/Desktop$ ./a.out
#define A 4
error
A 4
#define A
error
A
The rule "#define"+. is longer and gets precedence over the earlier #define even for correct input. You could say just this :-
"#define"[:space:]*$ {printf("error\n"); }
Consider using the -dvT options with flex to get detailed debug output. Also I am not sure if you need such extensive use of states for anything except maybe comments. But you would know better.