【问题标题】:debug code in standalone matlab独立 matlab 中的调试代码
【发布时间】:2011-06-28 09:37:52
【问题描述】:

假设我有一些函数foo 在独立应用程序中使用(即编译成带有mcc -m 的可执行文件),它有一个重要的中间结果bar。通常在函数完成后我不需要这个中间结果,因此它不是返回值。然而,出于开发和调试目的,能够使这个中间结果可访问是很有用的,我可以通过使用assignin 将中间结果放在某个调试工作区中来做到这一点。

现在的问题是assignin 在独立编译中是不可能的,如果代码中有assigninmcc 会报错。我想做的是仅在代码以交互方式运行而不是在编译为独立应用程序时才包含assignin。此外,这会加快速度,因为我在独立应用程序中无论如何都不需要中间结果,因此可以通过不在独立应用程序中执行分配来同时处理时间和/或内存。在任何其他编程环境中,都可以将其称为调试和发布模式下的编译。

在伪matlab中:

function res = foo()
  bar = some complicated formula
  if ~standalone
    assignin('debug', 'foo_bar', bar)
  end
  res = some complicated formula involving bar

问题是我不知道如何表达if ~standalone,首先我不知道如何测试是否处于独立模式,但更关键的是,这需要一些代码结构实际上导致mcc 完全忽略受保护的代码块,不尝试编译它,因为在独立模式下无法编译 assignin。

顺便说一句,这不仅对中间结果有价值,而且对于额外的数据收集也很有价值,额外的数据将在受保护的块中计算并通过assignin 导出。显然,这些额外的数据不应该在独立版本中计算,因为它没有任何用途。

matlab 中是否有任何这样的代码结构可以做到这一点,或者有更好的选择吗?到目前为止,在开发过程中,我一直在处理注释代码、取消注释和重新注释调试代码。

【问题讨论】:

    标签: debugging matlab matlab-compiler


    【解决方案1】:

    您可以使用全局调试结构并将变量存储在同名字段中,而不是使用 assignin 填充调试工作区。所有有效的变量名称也是有效的结构字段名称。您可以使用全局变量来实现这一点,但使用函数内部的持久变量可能会更好。这将适用于已编译或未编译的代码。

    首先,有一个定义调试模式的函数。

    function out = isdebugging(value)
    %ISDEBUGGING Get or set the global debugging state
    
    persistent state
    if isempty(state)
        state = false;
    end
    
    switch nargin
        case 0 % Getter
            out = state;
        case 1 % Setter
            state = value;
    end
    

    然后是一个用于存储调试值的函数,它仅在调试模式打开时保留值。

    function out = debugval(action, name, value)
    %DEBUGVAL Stash values for debugging
    
    persistent stash
    if isempty(stash)
        stash = struct;
    end
    
    % Short-circuit when not in debugging mode to save space
    if ~isdebugging()
        return;
    end
    
    switch action
        case 'get'
            out = stash.(name);
        case 'getall'
            out = stash;
        case 'set'
            stash.(name) = value;
        case 'list'
            out = fieldnames(stash);
        case 'remove'
            stash = rmfield(stash, name);
        case 'clear'
            stash = struct;
    end
    

    调试默认是禁用的,所以它会在编译版本中短路并且不会累积值。在您的交互式 Matlab 会话中使用 isdebugging(true) 手动启用它。这绕过了检测您是否正在运行已部署的问题。这也意味着您可以在编译的应用程序中启用和使用它,如果您想测试编译的代码以查看它在该上下文中的工作方式。您可以使用 GUI 按钮或环境变量来告诉编译的应用程序启用调试。

    isdebugging() 调用可以保护其他代码。但是我不会因为使用 isdebugging() 来保护除日志输出或值累积之外的任何东西而太过分。您不希望您的调试机制对代码的正确性产生副作用。

    还可以查看 Java 的 log4j 作为如何将运行时可配置调试输出合并到应用程序中的模型。您可以将其原理应用到 Matlab。

    【讨论】:

      【解决方案2】:

      使用函数isdeployed。 isdeployed 在 MCR 中运行时为 true,在 MATLAB 中运行时为 false。

      编辑:当然,这并不能解决编译问题。你可能需要找到一个替代assignin..

      【讨论】:

      • 不幸的是,我的旧版 matlab (6.1.0.450) 中似乎还没有这个功能,但mcc 会聪明地对待任何这样的 ifblock 并完全忽略它,还是会继续尝试编译 assignin 代码,因此编译失败。
      • 我自己没试过,但我认为编译会失败,这就是我添加编辑的原因。我猜 isdeployeds 主要用于 print 之类的功能,可以编译,但不会运行。
      猜你喜欢
      • 2011-03-22
      • 1970-01-01
      • 2012-08-18
      • 2011-03-13
      • 2011-10-21
      • 1970-01-01
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多