c++ - 了解一些 C++ 编码实践

标签 c++ debugging gdb

<分区>

我目前正在尝试了解以下代码 ( http://pastebin.com/zTHUrmyx) 是如何工作的,我的方法目前是在调试中编译软件并使用 gdb 单步执行代码。

但是,我遇到了“步骤”并不总是告诉我发生了什么的问题。我特别不清楚的是我无法进入的 EXECUTE {...}

我如何着手了解代码的作用?

   1     /*
   2     Copyright 2008 Brain Research Institute, Melbourne, Australia
   3
   4     Written by J-Donald Tournier, 27/06/08.
   5
   6     This file is part of MRtrix.
   7
   8     MRtrix is free software: you can redistribute it and/or modify
   9     it under the terms of the GNU General Public License as published by
  10     the Free Software Foundation, either version 3 of the License, or
  11     (at your option) any later version.
  12
  13     MRtrix is distributed in the hope that it will be useful,
  14     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16     GNU General Public License for more details.
  17
  18     You should have received a copy of the GNU General Public License
  19     along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.
  20
  21
  22     15-10-2008 J-Donald Tournier <d.tournier@brain.org.au>
  23     * fix -prs option handling
  24     * remove MR::DICOM_DW_gradients_PRS flag
  25
  26     15-10-2008 J-Donald Tournier <d.tournier@brain.org.au>
  27     * add -layout option to manipulate data ordering within the image file
  28
  29     14-02-2010 J-Donald Tournier <d.tournier@brain.org.au>
  30     * fix -coord option so that the "end" keyword can be used
  31
  32
  33 */
  34
  35 #include "app.h"
  36 #include "image/position.h"
  37 #include "image/axis.h"
  38 #include "math/linalg.h"
  39
  40 using namespace std;
  41 using namespace MR;
  42
  43 SET_VERSION_DEFAULT;
  44
  45 DESCRIPTION = {
  46   "perform conversion between different file types and optionally extract a subset of the input image.",
  47   "If used correctly, this program can be a very useful workhorse. In addition to converting images between different formats, it can be used to extract specific studies from a data set, extract a specific region of interest, flip the images, or to scale the intensity of the images.",
  48   NULL
  49 };
  50
  51 ARGUMENTS = {
  52   Argument ("input", "input image", "the input image.").type_image_in (),
  53   Argument ("ouput", "output image", "the output image.").type_image_out (),
  54   Argument::End
  55 };
  56
  57
  58 const gchar* type_choices[] = { "REAL", "IMAG", "MAG", "PHASE", "COMPLEX", NULL };
  59 const gchar* data_type_choices[] = { "FLOAT32", "FLOAT32LE", "FLOAT32BE", "FLOAT64", "FLOAT64LE", "FLOAT64BE",
  60     "INT32", "UINT32", "INT32LE", "UINT32LE", "INT32BE", "UINT32BE",
  61     "INT16", "UINT16", "INT16LE", "UINT16LE", "INT16BE", "UINT16BE",
  62     "CFLOAT32", "CFLOAT32LE", "CFLOAT32BE", "CFLOAT64", "CFLOAT64LE", "CFLOAT64BE",
  63     "INT8", "UINT8", "BIT", NULL };
  64
  65 OPTIONS = {
  66   Option ("coord", "select coordinates", "extract data only at the coordinates specified.", false, true)
  67     .append (Argument ("axis", "axis", "the axis of interest").type_integer (0, INT_MAX, 0))
  68     .append (Argument ("coord", "coordinates", "the coordinates of interest").type_sequence_int()),
  69
  70   Option ("vox", "voxel size", "change the voxel dimensions.")
  71     .append (Argument ("sizes", "new dimensions", "A comma-separated list of values. Only those values specified will be changed. For example: 1,,3.5 will change the voxel size along the x & z axes, and leave the y-axis voxel size unchanged.")
  72         .type_sequence_float ()),
  73
  74   Option ("datatype", "data type", "specify output image data type.")
  75     .append (Argument ("spec", "specifier", "the data type specifier.").type_choice (data_type_choices)),
  76
  77   Option ("scale", "scaling factor", "apply scaling to the intensity values.")
  78     .append (Argument ("factor", "factor", "the factor by which to multiply the intensities.").type_float (NAN, NAN, 1.0)),
  79
  80   Option ("offset", "offset", "apply offset to the intensity values.")
  81     .append (Argument ("bias", "bias", "the value of the offset.").type_float (NAN, NAN, 0.0)),
  82
  83   Option ("zero", "replace NaN by zero", "replace all NaN values with zero."),
  84
  85   Option ("output", "output type", "specify type of output")
  86     .append (Argument ("type", "type", "type of output.")
  87         .type_choice (type_choices)),
  88
  89   Option ("layout", "data layout", "specify the layout of the data in memory. The actual layout produced will depend on whether the output image format can support it.")
  90     .append (Argument ("spec", "specifier", "the data layout specifier.").type_string ()),
  91
  92   Option ("prs", "DW gradient specified as PRS", "assume that the DW gradients are specified in the PRS frame (Siemens DICOM only)."),
  93
  94   Option::End
  95 };
  96
  97
  98
  99 inline bool next (Image::Position& ref, Image::Position& other, const std::vector<int>* pos)
 100 {
 101   int axis = 0;
 102   do {
 103     ref.inc (axis);
 104     if (ref[axis] < ref.dim(axis)) {
 105       other.set (axis, pos[axis][ref[axis]]);
 106       return (true);
 107     }
 108     ref.set (axis, 0);
 109     other.set (axis, pos[axis][0]);
 110     axis++;
 111   } while (axis < ref.ndim());
 112   return (false);
 113 }
 114
 115
 116
 117
 118
 119 EXECUTE {
 120   std::vector<OptBase> opt = get_options (1); // vox
 121   std::vector<float> vox;
 122   if (opt.size())
 123     vox = parse_floats (opt[0][0].get_string());
 124
 125
 126   opt = get_options (3); // scale
 127   float scale = 1.0;
 128   if (opt.size()) scale = opt[0][0].get_float();
 129
 130   opt = get_options (4); // offset
 131   float offset = 0.0;
 132   if (opt.size()) offset = opt[0][0].get_float();
 133
 134   opt = get_options (5); // zero
 135   bool replace_NaN = opt.size();
 136
 137   opt = get_options (6); // output
 138   Image::OutputType output_type = Image::Default;
 139   if (opt.size()) {
 140     switch (opt[0][0].get_int()) {
 141       case 0: output_type = Image::Real; break;
 142       case 1: output_type = Image::Imaginary; break;
 143       case 2: output_type = Image::Magnitude; break;
 144       case 3: output_type = Image::Phase; break;
 145       case 4: output_type = Image::RealImag; break;
 146     }
 147   }
 148
 149
 150
 151
 152   Image::Object &in_obj (*argument[0].get_image());
 153
 154   Image::Header header (in_obj);
 155
 156   if (output_type == 0) {
 157     if (in_obj.is_complex()) output_type = Image::RealImag;
 158     else output_type = Image::Default;
 159   }
 160
 161   if (output_type == Image::RealImag) header.data_type = DataType::CFloat32;
 162   else if (output_type == Image::Phase) header.data_type = DataType::Float32;
 163   else header.data_type.unset_flag (DataType::ComplexNumber);
 164
 165  
 166   opt = get_options (2); // datatype
 167   if (opt.size()) header.data_type.parse (data_type_choices[opt[0][0].get_int()]);
 168
 169   for (guint n = 0; n < vox.size(); n++)
 170     if (isfinite (vox[n])) header.axes.vox[n] = vox[n];
 171
 172   opt = get_options (7); // layout
 173   if (opt.size()) {
 174     std::vector<Image::Axis> ax = parse_axes_specifier (header.axes, opt[0][0].get_string());
 175     if (ax.size() != (guint) header.axes.ndim())
 176       throw Exception (String("specified layout \"") + opt[0][0].get_string() + "\" does not match image dimensions");
 177
 178     for (guint i = 0; i < ax.size(); i++) {
 179       header.axes.axis[i] = ax[i].axis;
 180       header.axes.forward[i] = ax[i].forward;
 181     }
 182   }
 183
 184
 185   opt = get_options (8); // prs
 186   if (opt.size() && header.DW_scheme.rows() && header.DW_scheme.columns()) {
 187     for (guint row = 0; row < header.DW_scheme.rows(); row++) {
 188       double tmp = header.DW_scheme(row, 0);
 189       header.DW_scheme(row, 0) = header.DW_scheme(row, 1);
 190       header.DW_scheme(row, 1) = tmp;
 191       header.DW_scheme(row, 2) = -header.DW_scheme(row, 2);
 192     }
 193   }
 194
 195   std::vector<int> pos[in_obj.ndim()];
 196
 197   opt = get_options (0); // coord
 198   for (guint n = 0; n < opt.size(); n++) {
 199     int axis = opt[n][0].get_int();
 200     if (pos[axis].size()) throw Exception ("\"coord\" option specified twice for axis " + str (axis));
 201     pos[axis] = parse_ints (opt[n][1].get_string(), header.dim(axis)-1);
 202     header.axes.dim[axis] = pos[axis].size();
 203   }
 204
 205   for (int n = 0; n < in_obj.ndim(); n++) {
 206     if (pos[n].empty()) {
 207       pos[n].resize (in_obj.dim(n));
 208       for (guint i = 0; i < pos[n].size(); i++) pos[n][i] = i;
 209     }
 210   }
 211
 212
 213   in_obj.apply_scaling (scale, offset);
 214
 215
 216
 217
 218
 219
 220   Image::Position in (in_obj);
 221   Image::Position out (*argument[1].get_image (header));
 222
 223   for (int n = 0; n < in.ndim(); n++) in.set (n, pos[n][0]);
 224
 225   ProgressBar::init (out.voxel_count(), "copying data...");
 226
 227   do {
 228
 229     float re, im = 0.0;
 230     in.get (output_type, re, im);
 231     if (replace_NaN) if (gsl_isnan (re)) re = 0.0;
 232     out.re (re);
 233
 234     if (output_type == Image::RealImag) {
 235       if (replace_NaN) if (gsl_isnan (im)) im = 0.0;
 236       out.im (im);
 237     }
 238
 239     ProgressBar::inc();
 240   } while (next (out, in, pos));
 241
 242   ProgressBar::done();
 243 }

最佳答案

正如评论中所指出的,EXECUTE 似乎是一个宏,从上下文中可以明显看出是一个函数头(也许还有更多,例如一些全局变量和函数),所以花括号是函数体。

要了解 EXECUTE 的定义,您必须检查 header 。

但是,如果您可以在调试期间到达代码的某些部分,则可以在该位置插入 stringchar[],为其提供字符串化版本EXECUTE,因此您可以得到预处理器为 EXECUTE 在代码中的那个位置 发出的任何内容。

#define STR(x) #x
#define STRINGIFY(x) STR(x)
char c[] = STRINGIFY(EXECUTE);

这两个宏是一个已知的小宏技巧,可以将任何宏的内容作为字符串文字获取。尝试一下并在调试器中检查 char 数组以获取执行的内容。

我的大胆猜测:EXECUTE 是主函数或它的替代函数,OPTIONSARGUMENTS 描述了程序期望的参数以及您可以传递给它的命令行选项。这些宏和一些使用的函数和变量(get_optionsargument)是一个小框架的一部分,应该有助于命令行选项的使用、评估和用户信息。

关于c++ - 了解一些 C++ 编码实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16076022/

相关文章:

c - GDB 无法插入断点,无法访问地址 XXX 处的内存?

c++ - 在winsock2中使用select时,直接遍历 “readfds(fdsets)”是否合适?

c++ - 在结构上应用 std 算法?

java - 无法使用 Eclipse 运行 jUnit

c++ - gdb如何在dlopen打开的动态库中设置断点

c++ - 获取 GDB 便利变量中保存的值的符号信息

debugging - gdb:SSE 寄存器输出格式

c# - 从 C# 访问 C++ DLL 库

c++ - 使用 CMFCPropertyGrid 在可停靠 Pane 上捕获失去焦点事件

reactjs - SCSS - 可以使用react或chrome进行调试吗?