問題タブ [callstack]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
11 に答える
5261 参照

c++ - Cコンパイラはスタック変数を再配置できますか?

私は過去に組み込みシステムのプロジェクトに取り組み、スタック変数の宣言の順序を再配置して、結果の実行可能ファイルのサイズを小さくしました。たとえば、次のような場合:

これを次のように並べ替えます。

アラインメントの問題により、最初のものでは 12 バイトのスタック スペースが使用され、2 番目のものでは 8 バイトしか使用されませんでした。

これは C コンパイラの標準的な動作ですか、それとも私たちが使用していたコンパイラの欠点ですか?

必要に応じて、コンパイラはスタック変数を並べ替えて、実行可能サイズを小さくすることができるようにすべきだと私には思えます。C標準のいくつかの側面がこれを妨げていることが示唆されていますが、どちらにしても信頼できるソースを見つけることができませんでした.

おまけの質問ですが、これは C++ コンパイラにも当てはまりますか?

編集

答えが「はい」の場合、C/C++ コンパイラはスタック変数を再配置できます。確実にこれを行うコンパイラの例を挙げていただけますか? これを裏付けるコンパイラのドキュメントまたは同様のものを見たいと思います。

再編集

助けてくれてありがとう。ドキュメントについては、2003 年の GCC サミット議事録で発表された Naveen Sharma と Sanjiv Kumar Gupta による論文Optimal Stack Slot Assignment in GCC (pdf)を見つけることができました。

ここで問題となっているプロジェクトは、ARM 開発に ADS コンパイラを使用していました。そのコンパイラのドキュメントには、ARM-Thumb アーキテクチャがローカル スタック フレームでアドレスを計算する方法により、私が示したような宣言の順序付けによってパフォーマンスとスタック サイズが向上することが記載されています。そのコンパイラは、これを利用するためにローカルを自動的に再配置しませんでした。ここにリンクされている論文によると、2003年現在、GCCはスタックフレームを再配置してARM-Thumbプロセッサの参照の局所性を改善していませんが、可能であることを暗示しています.

これが GCC で実装されたことを明確に示すものは何も見つかりませんが、この論文は、あなたがすべて正しいという証拠として数えられると思います。再度、感謝します。

0 投票する
14 に答える
2083 参照

c++ - フレームポインタを変更できるものは何ですか?

現在、かなり大規模な C++ アプリケーション (CPU と RAM の使用量、およびコードの長さの点で大規模 - 100,000 行を超える) で、非常に奇妙なバグが発生しています。これは、デュアルコアの Sun Solaris 10 マシンで実行されています。このプログラムは株価フィードを購読し、ユーザーが設定した「ページ」に表示します (ページはユーザーがカスタマイズしたウィンドウ構造です - プログラムはユーザーがそのようなページを設定できるようにします)。このプログラムは、基盤となるライブラリの 1 つがマルチスレッドになるまで問題なく動作していました。これによって影響を受けるプログラムの部分は、それに応じて変更されました。私の問題に。

約 3 回の実行ごとに、プログラムは起動時にセグメンテーション違反を起こします。これは必ずしも難しいルールではありません。3 回続けてクラッシュし、5 回続けて動作することもあります。興味深いのはセグメンテーション違反です (読む: 痛い)。さまざまな形で現れる可能性がありますが、最も一般的なのは、関数 A が関数 B を呼び出し、関数 B に入るとフレーム ポインタが突然 0x000002 に設定されることです。機能 A:

これは単純なシグナルの実装です。impl_ と _A_a1 は、クラッシュ時のフレーム内で明確に定義されています。その命令を実際に実行すると、プログラム カウンター 0x000002 になります。

これは、その関数で常に発生するとは限りません。実際、かなりの数の場所で発生しますが、これはエラーの余地があまりない単純なケースの 1 つです。場合によっては、スタックに割り当てられた変数が理由もなく突然ジャンク メモリ (常に 0x000002) に置かれることがあります。また、同じコードが問題なく実行される場合もあります。それで、私の質問は、何がスタックをひどく壊すことができるのかということです. フレームポインタの値を実際に変更できるものは何ですか? 確かにそんな話は聞いたことがありません。私が考えることができる唯一のことは、配列に範囲外の書き込みをすることですが、それが発生した場合に発生するスタックプロテクターを使用して構築しました。ここでも、スタックの範囲内に収まっています。私もしない 各スレッドには独自のスタックがあるため (これはすべて pthread です)、別のスレッドが最初のスレッドのスタック上の変数を上書きする方法を確認してください。Linuxマシンでこれを構築しようとしましたが、セグメンテーション違反は発生しませんが、約3回に1回フリーズします。

0 投票する
35 に答える
526752 参照

javascript - JavaScript で呼び出し元の関数を見つけるにはどうすればよいですか?

コールスタックを見つける方法はありますか?

0 投票する
2 に答える
12170 参照

c# - 呼び出し元関数をどのように見つけますか?

「現在のメソッドを呼び出したメソッドを見つけるにはどうすればよいですか?」の正確な複製としてクローズされました。

これはc#で可能ですか?

0 投票する
1 に答える
1321 参照

winforms - このコールスタックを分析して、何が私のメソッドを呼び出しているかを確認するのを手伝ってください

さて、プレゼンターによって制御される、ロジックがほとんどない非常に単純なフォームがあります。フォームを初期状態にリセットするメソッド public void Reset() があります。これは、プレゼンターのみが、非常に特殊なケース (アクティビティ タイムアウトなど) で呼び出す必要があります。問題が発生していますが、いくつかのエッジケース (たとえば、アプリケーションがデータベース接続を失うことをシミュレートしている場合) で、Reset() メソッドが呼び出されるべきではないときに呼び出され、何が原因であるかを理解できません。 .

そこで、Reset() メソッドにトレースポイントを設定し、コールスタックを出力させました。奇妙なことに、さらに多くの疑問が生じました。Reset() への呼び出しがどこから来ているのかを理解するのを手伝ってくれる人はいますか? 私のコールスタックは以下です。

説明しなければならないことの 1 つは、コールスタックで確認できる DriverInterface2.UI.WinForms.NonInheritingForms.CheckInForm です。これは、ICheckInForm (関連するインターフェイス) の非常に単純な実装であり、単純に CheckInForm を作成し、それに委任します。これは、Castle Windsor を使用していて、Form から継承するクラスを配線するのが面倒だからです。いずれにせよ、そのメソッドの完全な内容は次のとおりです。

そして、コールスタックは次のとおりです。

0 投票する
17 に答える
141566 参照

assembly - スタックはアセンブリ言語でどのように機能しますか?

私は現在、スタックがどのように機能するかを理解しようとしているので、アセンブリ言語を独学することにしました。この本を使用しています:

http://savannah.nongnu.org/projects/pgubook/

私はGasを使用しており、 Linux Mintで開発を行っています。

私は何かに少し混乱しています:

私の知る限り、スタックは単なるデータ構造です。したがって、アセンブリでコーディングしている場合は、自分でスタックを実装する必要があると思いました。ただし、次のようなコマンドがあるため、これは当てはまらないようです

では、 x86アーキテクチャのアセンブリでコーディングし、Gas 構文を使用する場合: スタックは、既に実装されている単なるデータ構造なのでしょうか? それとも、実際にハードウェア レベルで実装されているのでしょうか。それとも別のものですか?また、他のチップ セットのほとんどのアセンブリ言語には、スタックが既に実装されていますか?

これが少しばかげた質問であることはわかっていますが、実際にはかなり混乱しています。

0 投票する
12 に答える
29659 参照

c++ - Windowsx64でスタックフレームをログに記録する方法

私はWin32でStackdumpsを使用して、すべてのリターンアドレスをログファイルに書き込みます。これらを後でマップファイルと照合します(私の記事[Post Mortem Debugging] [1]を参照)。

編集::問題は解決しました-以下の私自身の答えを参照してください。

Windows x64では、返信アドレスのみをログファイルに書き込む信頼できる方法が見つかりません。私はいくつかの方法を試しました:

試行1:ポインター演算:

これはデバッグバージョンでは正常に機能しますが、リリースバージョンではクラッシュします。Context.Rdiの値には、使用可能な値がありません。コンパイラ設定の違いを確認しました(Visual Studio 2005)。疑わしいものは何も見つかりませんでした。

試験2:StackWalk64を使用する

これは、リターンアドレスだけでなく、WHOLESTACKもダンプします。このアプローチを使用すると、ログファイルに約1000行が記録されます。これを使用することはできますが、行を検索する必要があり、スタックの一部のデータはたまたま有効なコードアドレスです。

試験3:バックトレースの使用

使用可能な情報がありません。

スタック内のリターンアドレスのみを書き出すようなスタックウォークをx64で実装した人はいますか?[StackTrace64] [2]、[StackWalker][3]などのアプローチを見てきました。それらはコンパイルされないか、非常に複雑です。基本的には簡単な作業です。

StackDump64.cppのサンプル

このサンプルを実行すると、次のログファイルの内容になります。

0 投票する
10 に答える
7397 参照

macos - Mac ABI が x86-32 に対して 16 バイトのスタック アラインメントを必要とするのはなぜですか?

古い PPC RISC システムや x86-64 の場合でも、この要件は理解できますが、実証済みの古い x86 の場合は? この場合、スタックは 4 バイト境界のみで整列する必要があります。はい、一部の MMX/SSE 命令では 16 バイトのアラインメントが必要ですが、それが呼び出し先の要件である場合は、アラインメントが正しいことを確認する必要があります。この追加の要件をすべての発信者に負担させるのはなぜですか? すべての呼び出しサイトがこの要件を管理する必要があるため、実際にはパフォーマンスが低下する可能性があります。何か不足していますか?

更新:これについてさらに調査し、社内の同僚と相談した結果、私はこれについていくつかの仮説を立てました。

  1. OS の PPC、x86、および x64 バージョン間の一貫性
  2. GCC codegen は、単純に「プッシュ」命令を実行するのではなく、sub esp,xxx を一貫して実行し、データをスタックに「移動」するようになりました。これは、一部のハードウェアでは実際に高速になる可能性があります。
  3. これは呼び出しサイトを少し複雑にしますが、呼び出し元がスタックをクリーンアップするデフォルトの "cdecl" 規則を使用する場合、余分なオーバーヘッドはほとんどありません。

最後の項目で私が抱えている問題は、呼び出し先がスタックをクリーニングすることに依存する呼び出し規則の場合、上記の要件がコード生成を実際に「醜く」することです。たとえば、一部のコンパイラが内部使用 (つまり、他の言語やソースからの呼び出しを意図していないコード) のために、より高速なレジスタ ベースの呼び出しスタイルを実装することを決定したものは何ですか? このスタックアライメントの問題は、いくつかのパラメーターをレジスターに渡すことによって達成されるパフォーマンスの向上の一部を無効にする可能性があります。

更新:これまでのところ、唯一の本当の答えは一貫性でしたが、私にはそれは少し簡単すぎる答えです。私は x86 アーキテクチャに関して 20 年以上の経験がありますが、パフォーマンスやその他の具体的なものではなく、一貫性が本当に理由である場合、開発者がそれを必要とするのは少しナイーブであることを丁重に提案します。彼らは、30 年近くにわたるツールとサポートを無視しています。特に、ツール ベンダーがツールを自社のプラットフォームにすばやく簡単に適応させることを期待している場合 (おそらくそうではないかもしれません... それApple です...)

このトピックは別の日かそこらにあげて、閉じます...

関連している

0 投票する
4 に答える
2045 参照

c++ - C++ でコール スタックのサイズを設定できますか? (vs2008)

比較的大きなローカル配列を割り当てるコードの例から作業しています。(正確には 32768) 同じことをしようとすると、スタック オーバーフローのように見える動作が発生します。今、私の例でスタックが私のアプリケーションよりも大きく設定されているのではないかと思っていました。これは可能ですか?もしそうならどのように?