6

正しいコード例:

#include "Python.h"
#include <string>

extern const int someConstant;

void some_function()
{
  const char *begin = NULL;
  const char *end = NULL;

  std::string s(begin, end);
  const int v = someConstant;
}

static PyMethodDef _G_methods[] =
{
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

PyMODINIT_FUNC initsf()
{
  PyObject *module;

  if (!(module = Py_InitModule("sf", _G_methods)))
  {
    return;
  }

  PyObject *pyerror = PyErr_NewException("fs.error", NULL, NULL);
  Py_INCREF(pyerror);


  PyModule_AddObject(module, "error", pyerror);
}

これは拡張モジュールドラフトです。可能な限りシンプル。元のドキュメントページからコピーされた空のメソッドテーブルと初期化関数があります。これには、2つの意図的なエラーが含まれています。

  • 変数someConstantが宣言されましたが、定義されていません。

  • 関数some_functionが定義されていますが、呼び出されることはありません。

dlopen / dlsymによってコンパイルおよびオープンされた場合:

sf.so: undefined symbol: someConstant

要求に応じ。しかし、Pythonインタープリターによってロードされた場合:

>>> from sf import *
Segmentation fault (core dumped)

そして最も奇妙なのは、コアファイルからダンプされたPythonのバックトレースです。

#0  0x00000bd6 in ?? ()
#1  0xb775c057 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/local/lib/python2.7/dist-packages/sf.so
#2  0xb6f9abb6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#3  0xb6c3fe30 in pkgInitConfig(Configuration&) () from /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12
#4  0xb6cf959e in ?? () from /usr/lib/python2.7/dist-packages/apt_pkg.so
#5  0x081949c1 in PyEval_EvalFrameEx ()
#6  0x0819af70 in PyEval_EvalCodeEx ()
#7  0x0819bb03 in PyImport_ExecCodeModuleEx ()
#8  0x0814bd40 in ?? ()
#9  0x080a38c2 in ?? ()
#10 0x0814c6d4 in ?? ()
#11 0x081031ae in ?? ()
...

Pythonのローダーはstd::stringコンストラクターを呼び出しているようです:-)。

そのため、スタックが破損しています。無効なモジュールのロード中、またはエラー処理後にアンロード中に発生します。サンプルコードが少し変更されていれば、それは決して起こりません。この動作はPython2.7.3/ Linux Ubuntu 10 / gcc 4.6.3で観察されており、Python 2.7.1 / FreeBSD 8.1 /gcc4.2.1では明らかに示されていません。

質問:

  1. Pythonのバグですか、それともサンプルコードにエラーがありますか?
4

1 に答える 1

3

そのスタックトレースをもう一度見てみましょう

#0 0x00000bd6 in ?? ()
#1 0xb775c057 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/local/lib /python2.7/dist-packages/sf.so
#2 0xb6f9abb6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/ lib/i386-linux-gnu/libstdc++.so.6
#3 /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12 からの pkgInitConfig(Configuration&) 内の 0xb6c3fe30
#4 0xb6cf959e in ?? () /usr/lib/python2.7/dist-packages/apt_pkg.so から

したがって、関数 inlibapt-pkg.soは、libstdc++.soモジュール内の関数を呼び出す関数を呼び出します。

関数が呼び出されることはありません。ただし、コードはstd::stringのいくつかの関数を使用してインスタンス化std::stringします。これらの関数は に含まれ*.so、まったく別の で使用される関数をオーバーライドし*.so、何らかの理由でクラッシュします。理由は完全にはわかりません。

私の本能によると、あなたは の代わりにgccを作成していました。共有オブジェクトのリンクはそのようには機能しないため、リンク時にエラーが発生することはありません。偶然にも既に読み込まれているため、読み込み時にエラーが発生することはありません。*.sog++libstdc++

gccまたはg++リンクするために使用していますか?を使ってみてくださいg++

于 2012-11-07T01:50:36.723 に答える