0

次のコード スニペットは、実行中の SW を抽出して簡略化したものです。リバース エンジニアリングを行っています (細かな点を気にせずに問題を強調しようとしました)。

win64 マシンで次のコードをビルドすると、操作中にクラッシュが発生します。

#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <stdlib.h>

using namespace std;

struct vaArgLookAlikePtrs 
{
    char* pPtr[1000];
};

int _tmain(int argc, _TCHAR* argv[])
{
    typedef std::basic_string<char> BasicString;
    static char buffer[132000];
    BasicString sFormatStr = "Var0=%s\nVar1=%.4f\nVar2=%d\n";
    struct vaArgLookAlikePtrs oData;

    void* pVoidPtr;
    int j=0;

    oData.pPtr[j] = "val0";
    j++;

    double dVar1 = 1.265;
    pVoidPtr = (void*)(&(oData.pPtr[j]));
    double* pDoublePtr = (double*)pVoidPtr;
    *pDoublePtr = dVar1;
    j++;// increment the buffer counter twice because doubles require 64 bits for     storage (This is how it works on the 32 bit machine)
    j++;

    int nVar2 = 2;
    pVoidPtr = &(oData.pPtr[j]);
    int* pIntPtr = (int*)pVoidPtr;
    *pIntPtr = nVar2;

    sprintf_s(buffer,sFormatStr.c_str(),oData);  // <-----

    cout << buffer << "\n";
    return 0;
}

いくつか質問があります:

  1. J++win32 プラットフォームでインデックス ( ) を 2 回インクリメントする必要があるのはなぜですか? - win32 プラットフォームは、double に対して char* ポイントを 2 回「ジャンプ」することをどのように認識していますか?
  2. なぜ sprintf_s は、win32 の oData (コンポジション コンテナー) から正しいフィールドを選択することを知っているのでしょうか? しかし、win64ではクラッシュしますか?

これは、32 ビットと 64 ビットのポインター サイズの違いによるものだと思いますが、動作を説明するためにあなたの助けを求めています。

4

2 に答える 2

1

あなたが投稿したコードはまったく意味がありません。可変引数関数の可変引数シーケンスを準備するアドホックな方法として配列を使用しようとしているようですか? 申し訳ありませんが、C でも C++ でもそのようには機能しません。可変引数関数の可変引数のシーケンスを「準備」する方法はまったくありません。

ある種の醜いハックを実装しようとしている場合は、 の実装をハッキングし続けてsprintf_sください。たぶん、あなたはそれを何らかの形で機能させるでしょう。しかし、これは C++ 言語とは関係ありません。そして、それはせいぜい無意味です。

于 2012-07-19T15:10:55.770 に答える