如何检查C中不同函数的调用顺序

如何检查C中不同函数的调用顺序,c,C,为了将某个变量MyVariable设置为TRUE,我必须检查系统中是否遵守了特定的函数调用顺序。 例如,我在系统中有不同的功能: uint8 myFunction1() { if (...) { return NOT_OK } else { return OK } } uint8 myFunction2() { if (...) { return NOT_OK } else

为了将某个变量MyVariable设置为TRUE,我必须检查系统中是否遵守了特定的函数调用顺序。 例如,我在系统中有不同的功能:

uint8 myFunction1()
{
    if (...)
    {
    return NOT_OK
    }
    else     
    {
    return OK
    }
}

uint8 myFunction2()
{
    if (...)
    {
    return NOT_OK
    }
    else     
    {
    return OK
    }
}


uint8 myFunction3()
{
    if (...)
    {
    return NOT_OK
    }
    else     
    {
    return OK
    }
}
仅当满足以下条件时,MyVariable=TRUE:

OK==myFunction1

OK==myFunction2

OK==myFunction3

确切地说,这个呼叫命令得到了尊重。 如何在C中检查调用顺序,但不涉及函数体,如设置一些标志等

我还是初学者,正在尝试C:


谢谢

没有直接和可移植的方法。也就是说,调试器擅长在到达函数时中断执行流,因此您可以使用调试器,或者在调用函数时使用调试函数发出警告

或者,一些链接器允许隐藏一些标识符并替换它们,因此,使用自定义和高级链接选项,您可以将所有对这些函数的调用替换为对自定义包装器的调用。但在这里,它只对特定的实现有意义,所以它也不是C方式


无论如何,这是一个如此不寻常的要求,我无法想象背后的实际理由。也许你可以提供更多关于你真正问题的背景…

这几乎肯定是一个XY问题。也就是说,您认为保存调用顺序是解决实际问题的方法,但您的实际问题可能是首先要确保不会以错误的顺序调用函数

所以解决这个问题最正确的方法就是重新设计程序。有人提到状态机是一种解决方案。另一种解决方案可能类似于函数指针数组,这是状态机的常见实现

也就是说,你可以做一些人工的事情来跟踪通话顺序,尽管我并不推荐这样做。例如:

#define CALL_ORDER_N 3

const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;


static void save_call (const char* func)
{
  call_order[call_order_i] = func;
  call_order_i++;
  if(call_order_i == CALL_ORDER_N)
  {
    call_order_i = 0;
  } 
}
其中调用顺序将最后3个函数调用保存为字符串文本的指针。函数save_调用通过从每个函数向数组传递_func__常量来更新此数组__func_uu保证像静态常量char[]一样工作,因此这是安全的。你可以这样做:

void myFunction1 (void)
{
  save_call(__func__);
  ...
}

void myFunction2 (void)
{
  save_call(__func__);
  ...
}

void myFunction3 (void)
{
  save_call(__func__);
  ...
}
然后查看通话顺序是否正确:

static bool is_call_order_ok (void)
{
  const char* expected_order [CALL_ORDER_N] = 
  {
    "myFunction1",
    "myFunction2",
    "myFunction3"
  };

  size_t co_i = call_order_i;

  for(size_t i=0; i<CALL_ORDER_N; i++)
  {
    if(strcmp(call_order[co_i], expected_order[i])==0)
    {
      co_i++;
      if(co_i == CALL_ORDER_N)
      {
        co_i = 0;
      } 
    }
    else
    {
      return false;
    }
  }

  return true;
}

当然,save_调用应该正确地放置在自己的.h/.c文件对中。

您知道状态机的概念吗?1.将函数包装到自定义函数中,在其中使用时间戳设置标志。2.设置myVariable时,比较时间戳和函数返回。3.这是C。没有其他方法可以自己实现。通常,随着程序的增长,您可能希望查看类似于在源文件中绘制控制流的图表。谢谢您提供的信息。但是调试程序在调试时非常棒。我需要在系统运行期间检查条件。更准确地说:我的要求是,只有在调用第一个myFunction1而不是myFunction2和myFunction3时,我才能在系统中更改为特定状态。
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define CALL_ORDER_N 3

const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;


static void save_call (const char* func)
{
  call_order[call_order_i] = func;
  call_order_i++;
  if(call_order_i == CALL_ORDER_N)
  {
    call_order_i = 0;
  } 
}

static bool is_call_order_ok (void)
{
  const char* expected_order [CALL_ORDER_N] = 
  {
    "myFunction1",
    "myFunction2",
    "myFunction3"
  };

  size_t co_i = call_order_i;

  for(size_t i=0; i<CALL_ORDER_N; i++)
  {
    if(strcmp(call_order[co_i], expected_order[i])==0)
    {
      co_i++;
      if(co_i == CALL_ORDER_N)
      {
        co_i = 0;
      } 
    }
    else
    {
      return false;
    }
  }

  return true;
}


void myFunction1 (void)
{
  save_call(__func__);
}


void myFunction2 (void)
{
  save_call(__func__);
}


void myFunction3 (void)
{
  save_call(__func__);
}



int main (void)
{
  printf("Call 1,2,3: ");
  myFunction1();
  myFunction2();
  myFunction3();
  printf(is_call_order_ok() ? "Ok\n" : "Failed\n");

  printf("Call 3,2,1: ");
  myFunction3();
  myFunction2();
  myFunction1();
  printf(is_call_order_ok() ? "Ok\n" : "Failed\n");

  printf("Call 1,1,1: ");
  myFunction1();
  myFunction1();
  myFunction1();
  printf(is_call_order_ok() ? "Ok\n" : "Failed\n");

  return 0;
}
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define CALL_ORDER_N 3

static bool save_call (const char* func, bool verify)
{
  bool result;

  static const char* call_order [CALL_ORDER_N] = {NULL};
  static size_t call_order_i = 0;
  static const char* expected_order [CALL_ORDER_N] = {NULL};

  size_t i = call_order_i;

  if(verify)                           // special case, verify the order
  {
    for(size_t expected=0; expected<CALL_ORDER_N; expected++)
    {
      if(call_order[i] == expected_order[expected])
      {
        i++;
        if(i == CALL_ORDER_N)
        {
          i = 0;
        } 
      }
      else
      {
        return false;
      }
    }
    return true;
  }

  if(expected_order[i] == NULL)        // register order of calls
  {
    expected_order[i] = func;
    result = true;
  }
  else                                 // save calls
  {
    call_order[i] = func;
    result = false;
  }

  call_order_i++;
  if(call_order_i == CALL_ORDER_N)
  {
    call_order_i = 0;
  } 

  return result;
}


void myFunction1 (void)
{
  if(save_call(__func__, false))
    return ;
  printf("Execute stuff in %s.\n", __func__);
}


void myFunction2 (void)
{
  if(save_call(__func__, false))
    return ;
  printf("Execute stuff in %s.\n", __func__);
}


void myFunction3 (void)
{
  if(save_call(__func__, false))
    return ;
  printf("Execute stuff in %s.\n", __func__);
}



int main (void)
{
  /* register call order: */
  myFunction1();
  myFunction2();
  myFunction3();


  printf("Call 1,2,3:\n");
  myFunction1();
  myFunction2();
  myFunction3();
  printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");

  printf("Call 3,2,1:\n");
  myFunction3();
  myFunction2();
  myFunction1();
  printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");

  printf("Call 1,1,1:\n");
  myFunction1();
  myFunction1();
  myFunction1();
  printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");

  return 0;
}