Im trying to set up a few functions in C where the program can read a specific rule and "fire" it depending on the date of the files. My problem is that while the function is working, the results are not right.
To put it in perspective, the program is imitating as a 'make' file. this 'make' file is meant to read some inputs through optarg(the input name, and the process), and then process the rules through another function. after that, the program simply checks the last date modified of the targets and the dependencies and 'fires' them depending on the dates.
The function itself needs to fire the rules if needed, but they are not working with the tests that I am using. Switching the condition around seemed to provide some result until I noticed that it was intentionally setting off unnecessary rules.
What should I consider in this case when im modifying my code to make it work? Do I need to alter the conditions again, or add more variables.
bool detectrules(struct stat *filea, struct stat *fileb){
double check = difftime(filea->st_mtime,fileb->st_mtime);
if (check > 0) return 1;
else return 0;
}
void comparerules(Rule *rulea){
int VALUE= 0;
struct stat TargetA;
struct stat DependA;
while(1){
if(rulea[VALUE].targets == NULL) break;
VALUE++;
}
VALUE--;
while(1){
if(VALUE < 0) break;
TargetA.st_mtime = 0;
stat (rulea[VALUE].targets[0], &TargetA);
int m = 0;
while(1){
if(rulea[VALUE].depends[m] == NULL){
m = 0;
break;
}
DependA.st_mtime = 0;
stat (rulea[VALUE].depends[m], &DependA);
if(detectrules(&TargetA, &DependA) == 1){
printf("Fire rule %i \n",VALUE+1);
break;
}
m++;
}
VALUE--;
}
}
Related
I have a task to make a StarCraft like program with multiple pthreads as workers.
So , I have multiple pthreads that run the following function:
void* scv(int num){
int minerals_carried = 0;
while(map_minerals_remaining>0){
minerals_carried = 0;
for(int i = 0; i<number_of_fields; i++){
if(fields[i].minerals != 0 && minerals_carried == 0){
if(pthread_mutex_trylock(&fields[i].mutex)==0){
sleep(1);
// mine returns int
minerals_carried = mine(&fields[i]);
printf("SCV%d is carrying %d minerals from field %d\n",num,minerals_carried,i);
if(pthread_mutex_unlock(&fields[i].mutex)!=0){
perror("pthread_mutex_unlock");
return NULL;
}
}else{
perror("pthread_mutex_trylock");
return NULL;
}
}
}
}
return NULL;
}
I create 5 pthreads and they all get created properly , but only the first one prints out like its supposed to do, and all the other ones dont seem to do anything. Any idea why that might be ?
EDIT :
I was asked to show how I initialized number_of_fields and fields and this is it:
I first declare them as global
typedef struct Mineral_Field_t{
pthread_mutex_t mutex;
int minerals;
}Mineral_Field;
Mineral_Field* fields;
int number_of_fields = 2;
And then I have the following piece of code at the start of the main function:
if(argv[1] != NULL){
number_of_fields = atoi(argv[1]);
}
fields = malloc(number_of_fields*sizeof(Mineral_Field));
I'm given a task to write a program that checks a piece of code, maximum of 20 lines of code, when the program runs you type in a function name, number of lines of code and type in the codes.
It's meant to search in the code and return if the function name you entered is a Library Function or User Defined Function or No Function if it doesn't find it, the code I've written is below, it doesn't work because I made mistakes and I've been trying to fix it but can't seem to figure it out, and I tried debugging to see where I made mistake, and I figured that in the function SearchRealisation it returns an error that
Run-Time Check Failure #2 - Stack around the variable 'buff' was
corrupted.
This program sample returns Library function instead of user defined function
type the function name: addition
Get count string in code: 9
int addition(int num1, int num2)
{
int result = num1 + num2; //trial
return result;
}
int main()
{
addition(8, 9);
}
Output is Library Function but correct output should be User Defined Function since it was defined in the code
void InputText(int length, char Text[MAX_STRINGS][MAX_COLUMNS])
{
//Repeat by Count String
gets_s(Text[0]);
for (int i = 0; i < length; i++)
gets_s(Text[i]);
//Output a string (starting with � zero and ending with Count String-1)
}
void OutMesseg(int param)
{
//Display one of three messages according to the parameter
if (param == -2)
printf("%s", "user defined function");
else if (param == -1)
printf("%s", "no function");
else
printf("%s", "library function");
}
char* DeleteComentsInString(char Text[MAX_STRINGS], char New[MAX_STRINGS])
{
char* a = strstr(Text, "//");
int len = strlen(Text);
if (a != NULL) len -= strlen(a);
strncpy(New, Text, len);
New[len] = '\0';
return New;
}
bool IsTypeC(char Word[MAX_STRINGS])
{
char ctype[6][MAX_STRINGS] =
{
"int",
"bool",
"char",
"float",
"double",
"void"
};
for (int i = 0; i < 6; i++)
{
if (strstr(Word, ctype[i]) != 0)
return true;
}
return false;
}
int SearchRealisation(int length, char Text[MAX_STRINGS][MAX_COLUMNS], int index_fanc, int& end)
{
int count = 0;
int start = -1;
end = -1;
char buff[MAX_STRINGS];
//Find first {
for (int i = index_fanc + 1; i < length && !count; i++)
{
if (strstr(DeleteComentsInString(Text[i], buff), "{") != NULL)
{
count++;
start = i;
}
}
//find last }
for (int i = start + 1; i < length && count; i++)
{
if (strstr(DeleteComentsInString(Text[i], buff), "{") != NULL)
count++;
else if (strstr(DeleteComentsInString(Text[i], buff), "}") != NULL)
count--;
if (!count)
end = i;
}
if (end == -1)
start = -1;
else
return start;
}
int SearchFunction(int length, char Text[MAX_STRINGS][MAX_COLUMNS], char FunctionName[MAX_COLUMNS], int& end)
{
//bool flag = false;
char commentDel[120];
int in;
for (int i = 0; i < length; ++i)
{
DeleteComentsInString(Text[i], commentDel);
if (strstr(commentDel, FunctionName) != NULL)
{
in = strlen(commentDel) - strlen(strstr(commentDel, FunctionName));
if ((in == 0 || (in != 0 && commentDel[in - 1] == ' ')) && (commentDel[in + strlen(FunctionName)] == ' ' || commentDel[in + strlen(FunctionName)] == '(') && strstr(commentDel, ";") == NULL)
{
return SearchRealisation(length, Text, i, end);
}
}
}
end = -1;
return -1;
}
int SearchResult(int length, char Text[MAX_STRINGS][MAX_COLUMNS], char FunctionName[MAX_COLUMNS])
{
int index;
int end;
int start = SearchFunction(length, Text, FunctionName, end);
if (start == -1)
return -1;
index = SearchFunction(length, Text, FunctionName, end);
if (index < 0)
return -2;
return index;
}
int findFunction(char string[MAX_STRINGS][MAX_COLUMNS], char* functName, int M)
{
return 0;
}
int main()
{
int length = 0;
char Code[MAX_STRINGS][MAX_COLUMNS] = { 0 };
char FunctionName[MAX_COLUMNS];
//char ConstantName[MAX_STRINGS];
printf("type the function name: ");
scanf("%s", &FunctionName);
printf("Get count string in code: ");
scanf("%d", &length);
InputText(length, Code);
printf("\n");
OutMesseg(SearchResult(length, Code, FunctionName));
return 0;
}
Well, you have been given a very difficult task:
There's no way to check this, as functions are resolved by a dynamic process that depends on your filesystem state, which is not available at runtime, after you have already compiled your program.
How do you distinguish a function that is compiled in a separate (but user defined) compilation unit from a system defined function? (e.g. double log(double);) that is defined in a math library? There is no way: the linker gets both from a different place (in the first case it gets it from the place you compiled the separate module, in the system case it gets it from a common library directory that has all the system related functions), but you don't have that information available at runtime).
In order to do this task feasible, you'd at least have the full set of source code files of your program. Preprocess them with the cpp(1) preprocessor (so you bypass all the macro expansion invocations) and then check for all function calls in the source code that are not provided in the full set of sources you have. This is quite similar to what the linker does. After compilation, the compiler leaves an object file with the compiled code, and a symbol table that identifies all the unresolved identifiers, and more important all the provided identifiers from this module. The linker then goes on all your modules trying to solve the unknowns, and for each that it doesn't have a solution in your code, it goes to the library directory to search for it. If it doesn't find it in either one, it fails telling you something is wrong.
In my opinion, you have been given a trap task, as the C language preprocess its input (this is something you should do, as many functions are hidden in the internals of macro bodies), then parse the code (for this, you need to write a C parser, which is no trivial task) to select which identifiers are defined in your code and which aren't. Finally you need to check all the calls you do in the code to divide the set in two groups, calls that are defined (and implemented) in your code, and calls that aren't (implemented, all the calls the compiler needs must be defined with some kind of prototype).
It's my opinion, but you have not a simple task, solvable in a short program (of perhaps one hundred lines) but a huge one.
Thanks a lot to everyone that answered I came up with a way to search the code for function definition and thereby return a value if its defined or not, or not even found, might not be the best solution to the task but works so far
I'm writing a program that will simulate a randomized race between runners who are climbing up a mountain where dwarf orcs (dorcs) are coming down the mountain to attack the runners. It begins with two runners named harold and timmy at the bottom of the mountain. The runners make their way up the mountain in randomized moves where they may make progress forward up the mountain, or they may slide back down the mountain. Dorcs are randomly generated, and they inflict damage on a runner if they collide. The simulation ends when one of the runners reaches the top of the mountain, or when both runners are dead.
I'm struggling with a part where I have to implement the actual race loop. Once the race is initialized, the race loop will iterate until the race is over. This happens when either a winner has been declared, or when all runners are dead.
Every iteration of the race loop will do the following:
with 30% probability, dynamically allocate a new dorc as an EntityType structure, and initialize it as follows:
(a) a dorc’s avatar is always “d”
(b) each dorc begins the race at the top of the mountain, which is at row 2
(c) with equal probability, the dorc may be placed either in the same column as timmy, or in the same column as the harold, or in the column exactly half-way between the two
(d) add the new dorc to the race’s array of dorcs
(e) using the pthread_create() function, create a thread for the new dorc, and save the thread pointer in the dorc’s entity structure; the function that each dorc thread will execute is the void* goDorc(void*) function that you will implement in a later step; the parameter to the goDorc() function will be the EntityType pointer that corresponds to that dorc
I guess I'm confused with the logic of how to approach this. I decided to make a function called isOver() to indicate if the race is over, and then a separate function called addDorc() to initialize the Dorc elements and do all the requirements above.
In isOver(), I attempt to add a dorc object to the dorcs array by doing addDorc(race); with every iteration of the race loop/if the race hasn't ended or no one died. But I keep getting the error:
control.c:82:3: error: too few arguments to function ‘addDorc’
addDorc(race);
The problem is I don't think I can manually declare all the parameters in addDorc() because some elements like the "path" argument are based on probability. As mentioned above, with equal probability, the dorc may be placed either in the same column as timmy, or in the same column as the harold, or in the column exactly half-way between the two. The issue is I don't know how to factor this random value when calling addDorc() and would appreciate some help. I also don't know if I'm doing the "with 30% probability, dynamically allocate a new dorc as an EntityType structure" correctly and would be grateful for some input on that as well.
defs.h
typedef struct {
pthread_t thr;
char avatar[MAX_STR];
int currPos;
int path;
} EntityType;
typedef struct {
EntityType ent;
char name[MAX_STR];
int health;
int dead;
} RunnerType;
typedef struct {
int numRunners;
RunnerType *runners[MAX_RUNNERS];
int numDorcs;
EntityType *dorcs[MAX_DORCS];
char winner[MAX_STR];
int statusRow;
sem_t mutex;
} RaceInfoType;
void launch();
int addDorc(RaceInfoType*, char*, int, int);
int isOver(RaceInfoType*);
void initRunners(RaceInfoType*);
int addRunner(RaceInfoType*, char*, char*, int, int, int, int);
int randm(int);
void *goRunner(void*);
void *goDorc(void*);
RaceInfoType *race;
control.c
void launch(){
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;
initRunners(race);
if (sem_init(&race->mutex, 0, 1) < 0) {
printf("semaphore initialization error\n");
exit(1);
}
strcpy(race->winner, " ");
srand((unsigned)time(NULL));
int i;
for(i = 0; i < race->numRunners; ++i){
pthread_create(&(race->runners[i]->ent.thr), NULL, goRunner, " ");
}
race->numDorcs = 0;
}
int addDorc(RaceInfoType* race, char *avatar, int path, int currPos){
if(race->numDorcs == MAX_DORCS){
printf("Error: Maximum dorcs already reached. \n");
return 0;
}
race->dorcs[race->numDorcs] = malloc(sizeof(EntityType));
int timmysColumn = race->dorcs[race->numDorcs]->currPos;
int haroldsColumn = race->dorcs[race->numDorcs]->currPos;
int halfwayColumn = (timmysColumn+haroldsColumn)/2;
int r = rand()%100;
pthread_t dorc;
if(r <= 30){
strcpy(race->dorcs[race->numDorcs]->avatar, "d");
race->dorcs[race->numDorcs]->currPos = 2;
if(r <= 33){
race->dorcs[race->numDorcs]->path = timmysColumn;
}else if(r <= 66){
race->dorcs[race->numDorcs]->path = haroldsColumn;
}else{
race->dorcs[race->numDorcs]->path = halfwayColumn;
}
pthread_create(&dorc, NULL, goDorc, " ");
}
race->numRunners++;
}
int isOver(RaceInfoType* race){
int i;
for(i = 0; i < race->numRunners; ++i){
if((race->winner != " ") || (race->runners[race->numRunners]->dead = 1)){
return 1;
}
addDorc(race);
return 0;
}
}
void initRunners(RaceInfoType* r){
addRunner(r, "Timmy", "T", 10, 35, 50, 0);
addRunner(r, "Harold", "H", 14, 35, 50, 0);
}
int addRunner(RaceInfoType* race, char *name, char *avatar, int path, int currPos, int health, int dead){
if(race->numRunners == MAX_RUNNERS){
printf("Error: Maximum runners already reached. \n");
return 0;
}
race->runners[race->numRunners] = malloc(sizeof(RunnerType));
strcpy(race->runners[race->numRunners]->name, name);
strcpy(race->runners[race->numRunners]->ent.avatar, avatar);
race->runners[race->numRunners]->ent.path = path;
race->runners[race->numRunners]->ent.currPos = currPos;
race->runners[race->numRunners]->health = health;
race->runners[race->numRunners]->dead = dead;
race->numRunners++;
return 1;
}
Caveat: Because there's so much missing [unwritten] code, this isn't a complete solution.
But, I notice at least two bugs: the isOver bugs in my top comments. And, incrementing race->numRunners in addDorc.
isOver also has the return 0; misplaced [inside the loop]. That should go as the last statement in the function. If you had compiled with -Wall [which you should always do], that should have been flagged by the compiler (e.g. control reaches end of non-void function)
From that, only one "dorc" would get created (for the first eligible runner). That may be what you want, but [AFAICT] you want to try to create more dorcs (one more for each valid runner).
Also, the bug the compiler flagged is because you're calling addDorc(race); but addDorc takes more arguments.
It's very difficult to follow the code when you're doing (e.g.) race->dorcs[race->numDorcs]->whatever everywhere.
Better to do (e.g.):
EntityType *ent = &race->dorcs[race->numDorcs];
ent->whatever = ...;
Further, it's likely that your thread functions would like a pointer to their [respective] control structs (vs. just passing " ").
Anyway, I've refactored your code to incorporate these changes. I've only tried to fix the obvious/glaring bugs from simple code inspection, but I've not tried to recompile or address the correctness of your logic.
So, there's still more work to do, but the simplifications may help a bit.
void
launch(void)
{
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;
initRunners(race);
if (sem_init(&race->mutex,0,1) < 0) {
printf("semaphore initialization error\n");
exit(1);
}
strcpy(race->winner," ");
srand((unsigned)time(NULL));
int i;
for (i = 0; i < race->numRunners; ++i) {
RunnerType *run = &race->runners[i];
EntityType *ent = &run->ent;
pthread_create(&ent->thr,NULL,goRunner,ent);
}
race->numDorcs = 0;
}
int
addDorc(RaceInfoType* race,char *avatar,int path,int currPos)
{
if (race->numDorcs == MAX_DORCS) {
printf("Error: Maximum dorcs already reached. \n");
return 0;
}
EntityType *ent = malloc(sizeof(*ent));
race->dorcs[race->numDorcs] = ent;
int timmysColumn = ent->currPos;
int haroldsColumn = ent->currPos;
int halfwayColumn = (timmysColumn + haroldsColumn) / 2;
int r = rand()%100;
#if 0
pthread_t dorc;
#endif
if (r <= 30) {
strcpy(ent->avatar,"d");
ent->currPos = 2;
if (r <= 33) {
ent->path = timmysColumn;
} else if (r <= 66) {
ent->path = haroldsColumn;
} else {
ent->path = halfwayColumn;
}
pthread_create(&ent->thr,NULL,goDorc,ent);
}
#if 0
race->numRunners++;
#else
race->numDorcs += 1;
#endif
}
int
isOver(RaceInfoType* race)
{
int i;
for (i = 0; i < race->numRunners; ++i) {
#if 0
if ((race->winner != " ") ||
(race->runners[race->numRunners]->dead = 1))
return 1;
#else
RunnerType *run = &race->runners[i];
if ((race->winner != " ") || (run->dead == 1))
return 1;
#endif
addDorc(race);
#if 0
return 0;
#endif
}
#if 1
return 0;
#endif
}
void
initRunners(RaceInfoType* r)
{
addRunner(r,"Timmy","T",10,35,50,0);
addRunner(r,"Harold","H",14,35,50,0);
}
int
addRunner(RaceInfoType* race,char *name,char *avatar,int path,int currPos,
int health,int dead)
{
if (race->numRunners == MAX_RUNNERS) {
printf("Error: Maximum runners already reached. \n");
return 0;
}
RunnerType *run = malloc(sizeof(*run));
race->runners[race->numRunners] = run;
strcpy(run->name,name);
EntityType *ent = &run->ent;
strcpy(ent->avatar,avatar);
ent->path = path;
ent->currPos = currPos;
run->health = health;
run->dead = dead;
race->numRunners++;
return 1;
}
UPDATE:
I noticed in addDorc(), you put pthread_t dorc; in an if statement. I don't quite understand what my if statement is actually supposed to be checking though.
I forgot to mention/explain. I wrapped your/old code and my/new code with preprocessor conditionals (e.g.):
#if 0
// old code
#else
// new code
#endif
After the cpp stage, the compiler will only see the // new code stuff. Doing this was an instructional tool to show [where possible] what code you had vs what I replaced it with. This was done to show the changes vs. just rewriting completely.
If we never defined NEVERWAS with a #define NEVERWAS, then the above block would be equivalent to:
#ifdef NEVERWAS
// old code ...
#else
// new code
#endif
Would it still be under the if(r <= 30) part like I did in my original code?
Yes, hopefully now, it is more clear. #if is a cpp directive to include/exclude code (as if you had edited that way). But, a "real" if is an actual executable statement that is evaluated at runtime [as it was before], so no change needed.
My other concern is it doesn't look like dorc is used anywhere in the function because you write pthread_create(&ent->thr,NULL,goDorc,ent); which seems to use ent instead?
That is correct. It is not used/defined and the value goes to ent->thr. As you had it, the pthread_t value set by pthread_create would be lost [when dorc goes out of scope]. So, unless it's saved somewhere semi-permanent (e.g. in ent->thr), there would be no way to do a pthread_join call later.
So I've got a weird problem and can't seem to solve it. I have an ADT called TEAM:
typedef struct Team {
char *name;
int points;
int matches_won;
int goal_difference;
int goals_for;
}TEAM;
I created a function to initialize variables of the TEAM* type with a given name:
TEAM *createTEAM (char *name){
int error_code;
if (name != NULL){
if(strcmp(name, "") != 0){
TEAM *new_team = (TEAM*)malloc(sizeof(TEAM));
new_team->name = (char*)malloc(sizeof(char)*strlen(name));
strcpy(new_team->name, name);
new_team->points = 0;
new_team->matches_won = 0;
new_team->goal_difference = 0;
new_team->goals_for = 0;
return new_team;
}else{
error_code = EMPTY_STRING_CODE;
}
} else {
error_code = NULL_STRING_CODE;
}
printf("Erro ao criar time.\n");
printError(error_code);
return NULL;
}
I also created a function to delete one of these TEAM* variables properly:
void deleteTEAM (TEAM *team_to_remove){
free(team_to_remove->name);
team_to_remove->name = NULL;
free(team_to_remove);
team_to_remove = NULL;
}
But when one or multiple test functions that I created (example below) run, the program sometimes crashes, sometimes doesn't. I've noticed that changing the names I use affects whether it crashes or not, even if they don't affect the test results.
int create_team_01(){
int test_result;
TEAM *Teste = createTEAM("Cruzeiro");
if (strcmp(Teste->name, "Cruzeiro") == 0){
test_result = TRUE;
}else test_result = FALSE;
_assert(test_result); //just a macro function that will check the argument and return 1 if it's false
deleteTEAM(Teste);
return 0;
}
I don't see any problems with memory allocation or freeing. Still, the debugger complains a lot about the first free() (can't find bounds) of the deleteTEAM function. Any ideas? Thanks a lot in advance for any help.
P.S.: I've even tried checking the mallocs' results, but it doesn't seem to be the problem either, so I removed it for the sake of simplicity.
I think the following code is normal (and malloc/free is similar):
int foo(){
FILE *fp = fopen("test.in", "r");
int i;
for(i = 0; i < NUM; i ++){
if(Match(fp, i)){
fclose(fp);
return i;
}
}
fclose(fp);
return 0;
}
As we can see fclose(fp) appears twice in the code. It will appear more if there are other return statements in the function foo. However, it is troublesome that I have to write fclose(fp) many times. One solution is just one return for one function. However, multiple returns is sometimes useful. Is there any other solution?
PS: As I know, there is a macro(with-open-file) in lisp.
(with-open-file (stream-var open-argument*)
body-form*)
It could open and close file for us.
The use of break often helps:
int foo() {
FILE *fp = fopen("test.in", "r");
int i, result;
result = 0;
for(i = 0; i < NUM; i ++){
if(Match(fp, i)){
result = i;
break;
}
}
fclose(fp);
return result;
}
In the source code of linux kernel, there are many functions that have to take care of locks and other resource on return. And they conventionally add a cleanup label at the end of the function, and goto there whenever early return occurs. I personally recommend this usage to avoid duplicate code, and maybe this is the only sane usage of goto.
An extra layer of indirection can ensure you don't miss an exit from the function:
int foo(FILE *fp)
{
int i;
for(i = 0; i < NUM; i ++){
if(Match(fp, i)){
return i;
}
}
return 0;
}
int foo_wrapper(void)
{
FILE *fp = fopen("test.in", "r");
int out = foo(fp);
fclose(fp);
return out;
}
I'll expand on exception handling via goto (mentioned in #Charles Peng's answer):
You do it something like:
int func(...)
{
...
f = fopen(...);
if (f == NULL) {
log("failed opening blah blah...");
goto err;
}
...
m = malloc(...)
if (m == NULL) {
log("blah blah...");
goto err_close_f;
}
...
if (do_something(...) < 0) {
log("blah blah...");
goto err_close_f;
}
...
r = alloc_resource(...)
if (r == 0) {
log("blah blah...");
goto err_free_m;
}
...
return 0;
err_free_m:
free(m);
err_close_f:
fclose(f);
err:
return -1;
}
The advantage of this is that it's very maintainable. Resource acquisition and release has a somewhat symmetrical look when using this idiom. Also, resource release is out of the main logic, avoiding excessive clutter where it annoys the most. It's quite trivial to check that error handling of functions is right (just check that it jumps to the appropiate point, and that the previous label releases any acquired resource)...
A return statement NOT at the end of a function is the equivalent of a goto statement. Even though it may appear as though some functions are simpler with multiple return statements it has been my experience while maintaining various code bases that the ones with only 1 exit point from every function are easier to maintain.