簡體   English   中英

為什么這段代碼會編譯

[英]Why does this code compile

我不明白為什么這段代碼編譯並運行沒有錯誤:

#include <iostream>
#include <stdio.h>
#include <Eigen/Dense>

int
main (int argc, char *argv[])
{
  typedef Eigen::Matrix<double, 5, 3/*FIXME: Should be 5*/> Matrix5;

  Matrix5 test;
  test << 2,0,0,1,1, 
          0,2,0,1,1,
          0,0,2,2,2,
          0,1,2,0,0,
          0,1,1,0,0; // We filled a 5*5 matrix in a 5*3 matrix

  //std::cout << "Test matrix:\n" << test << std::endl;
  return (0);
}

這是我編譯代碼的方式:

g++ test_eigen.cpp -o test_eigen -I/usr/include/eigen3 -O3 -DEIGEN_NO_DEBUG

取消注釋std::cout ,編譯,再次運行,你會得到一個分段錯誤。 我在Ubuntu 14.04上使用Eigen 3.2.0-8。

如建議; 這是Valgrind的輸出(用std::cout評論):

$ valgrind ./test_eigen
==12380== Memcheck, a memory error detector
==12380== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==12380== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==12380== Command: ./test_eigen
==12380== 
==12380== 
==12380== HEAP SUMMARY:
==12380==     in use at exit: 0 bytes in 0 blocks
==12380==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==12380== 
==12380== All heap blocks were freed -- no leaks are possible
==12380== 
==12380== For counts of detected and suppressed errors, rerun with: -v
==12380== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

寫過數據結構的分配邊界(例如,將5x5矩陣寫入分配的5x3)是未定義的行為。 它可能會或可能不會崩潰,不幸的是,甚至可能會在沒有明顯錯誤的情況下完成。

使用valgrind運行代碼以查明與您描述的類似的內存問題。

我懷疑你編譯時禁用了斷言。

Eigen重載operator<<以使用逗號分隔列表初始化矩陣。 (請注意,這也意味着在幕后潛伏着逗號運算符)。 逗號分隔的項目列表可以包含數字,但它也可以包含向量或其他矩陣。

這種靈活性需要付出代價。 Eigen在編譯時無法判斷逗號分隔列表包含太多或太少的項目。 它反而在運行時檢測到太多/太少的項目,並通過eigen_assert投訴。 如果已經使用已禁用的斷言進行編譯,則可以讓過度完整的項目列表從SIGABRT更改為未定義的行為。

這種事情總是以未定義的行為發生,添加語句會神奇地讓代碼運行而不會出錯。 不要把它當作事情沒問題的標志。 它碰巧跑了。 未定義的行為總是很糟糕。 僅僅因為它在某些情況下“有效”並不意味着您的代碼在下次使用該程序時不會重新格式化您的硬盤。

為什么這段代碼會編譯?

因為編譯器無法知道在編譯時傳遞給operator<<元素數量。 該信息僅在運行時可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM