Ограничить время выполнения функции в с
Я хотел бы ограничить выполнение функции в чистом C, не останавливая всю программу.
Я полагаю, что самым близким моментом на stackru.com было последнее замечание в этой теме: как ограничить время выполнения функции в C/POSIX?
Был некоторый разговор об использовании setjmp и longjm, помещенных после функции, чтобы ограничить время, но поток умер.
Есть ли кто-нибудь, кто знает, действительно ли это возможно?
ура
2 ответа
Я вижу два варианта: первый проверяет время каждые несколько строк кода и return
если это слишком много, но я не думаю, что это хорошая идея.
Во-вторых, вы можете использовать темы. Запустите две функции одновременно, одну синхронизирующую другую, если время слишком велико, то первая убивает. Теперь я почти уверен, что в Windows и Linux есть разные библиотеки для создания потоков, поэтому вы можете попробовать использовать библиотеку, которая работает на всех платформах, например, эта может быть http://openmp.org/wp/
Я не слишком знаком с этой библиотекой и потоками в целом, но я надеюсь, что это поможет
Хотя может быть полезно опубликовать мое решение. Это комбинация этого поста http://cboard.cprogramming.com/c-programming/148363-limit-execution-time-function.html и примера IPC TPL, найденного здесь: https://github.com/troydhanson/tpl/blob/master/doc/examples.txt.
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include "tpl.h"
//This example contains two different parts:
//1) The alarm is a execution timer for the function doWork
//2) There is a need, that if the execution exits correctly, that the chid value of i, that we are modifying be passes
typedef struct TEST_STRUCT
{
int i;
double sum;
} testStruct;
int doWork(testStruct * ts)
{
int y;
for(y=0; y<3; y++)
{
sleep(1);
printf("Working: %d\n", ts->i);
ts->i++;
ts->sum += (double)ts->i;
}
return 0;
}
int main()
{
testStruct * ts = (testStruct *)(calloc(1, sizeof(testStruct)));
ts->i = 7;
ts->sum = 4.0;
tpl_node *tn;
int fd[2];
pipe(fd);
int y;
for(y=0; y<10; y++)
{
pid_t childPID = fork();
if (childPID==0)
{
unsigned secsLeft;
alarm(10);
doWork(ts);
printf("\t->%d\n", ts->i);
printf("\t->%p\n", (void*) &ts->i);
tn = tpl_map("S(if)", ts);
tpl_pack( tn, 0 );
tpl_dump( tn, TPL_FD, fd[1]);
tpl_free( tn );
secsLeft = alarm(0);
exit(0);
}
else
{
//IMPORTANT TO PUT IT HERE: In case the buffer is too big, TPL_DUMP will wait until it can send another and hang
tn = tpl_map( "S(if)", ts );
tpl_load( tn, TPL_FD, fd[0]);
int status;
wait(&status);
if(WIFSIGNALED(status))
{
// child was interrupted
if (WTERMSIG(status) == SIGALRM)
{
printf("Interrupted\n");
// child interrupted by alarm signal
}
else
{
printf("Should not happend\n");
// child interrupted by another signal
}
}
else
{
tpl_unpack(tn,0);
tpl_free( tn );
printf("\t->%d\n", ts->i);
printf("\t->%p\n", (void*) &ts->i);
printf("Success\n");
}
}
}
return 0;
}
По сути, мы разветвляем программу, в которой ребенок выполняет задание, а родитель ожидает его завершения. Ребенок содержит тревогу, которая, если истина сигнализирует родителю, что он существовал таким образом. Если он завершается (как показано в этом примере), дочерний объект отправляет объектную функцию родителю в виде буфера TPL.