1

(或者,当被 1023 整除时(见下面的更新 3))

我正在寻找一个错误,当包含要提取的数据的文件的大小可以被 1024 整除时,就会出现一个错误。在这种情况下,提取似乎一直工作到完成,但最后却失败了。

考虑到在这种情况下可能会发生一些奇怪的事情(当有一个文件的大小是 1024 的倍数时),我在代码中搜索了对“1024”的任何引用,但没有具体提到“1024”的实时代码。”

我确实在获取代码中发现了一件我认为看起来很奇怪的东西,即:

connFrmSitesData.Dispose();
connFrmSitesData = null;

将表单设置为 null 是否可能导致问题?有什么理由让它存在吗?

更新

我发现这段代码让我想知道:

string theMessage = new string( '\x00', 1023 );

...如果它可能与问题无关。

更新 2

现在我看到那个字符串 (theMessage)* 甚至没有被使用;我能够将其注释掉(在所有三个类似声明且此后未使用的地方)。

那么为什么在这段代码中有:

bool    retVal      = false;            
string  theMessage  = new string( '\x00', 1023 ); // fill 1023 bytes with nulls
. . .
    if( retVal = Util.NetSendCommand( rc.command ) )

...“retVal”是变灰的变量(我假设是 Resharper),而“theMessage”没有变灰?

  • 还有一个“正常”** theMessage 声明为类私有:

    私人字符串 theMessage;

** “正常”,因为它没有用重载的构造函数实例化。

更新 3

我可能已经找到了问题区域(实际上在不同的项目中 - 项目调用的 .DLL)。

此代码是可疑的,因为 MAXREAD = 1023。

任何人都可以看到这会导致精确大小的文件失败的任何问题吗?例如,如果先前的 Read 已获得所有内容,对 bReader.Read() 的调用会失败吗?

还是这里的某个地方潜伏着其他问题?

BinaryReader bReader          = null;
. . .
bReader = new BinaryReader( theN_Stream );
. . .
fsWriteText = new FileStream( destFPath, FileMode.Create, FileAccess.Write );
. . .
bWriter = new BinaryWriter( fsWriteText );
. . .

/* --------------------------------------- *
 *   Incoming message may be larger than 
 *   the buffer size.
 * --------------------------------------- */ 
int index     = 0;
int indexLast = 0;
int next2Read = MAXREAD;

try
{
    // keep doing this until no data available on the stream, ...
    do
    {
        next2Read         = MAXREAD; //1023
        longString        = "";

    Array.Clear( readbuffer, 0, MAXREAD );

    numberOfBytesRead = bReader.Read( readbuffer, 0, next2Read );

    indexLast  = index;
    realTotBytesRead += numberOfBytesRead; 
    index     += numberOfBytesRead;
    nBytes    += numberOfBytesRead;
    xferProgress = nBytes.ToString() + "|" + fsize.ToString();
    OnProgressChanged(xferProgress);

    if( bWriter != null )
        {
            if( bWriter.BaseStream.CanWrite )
            {
                bWriter.Write( readbuffer, 0, numberOfBytesRead );
            }
        }

    if( index >= fsize )
    {
        haveFinishedRead = true;
        break;
    }

    if( !theN_Stream.CanRead )
    {
        break;
    }
} while( index < fsize );

更新 4

在试图解决这个问题的过程中,我编译了(不是双关语)以下注释。

// readbuffer 是一个字节数组。// bReader 是一个二进制阅读器

“索引”从 0 开始,分配读取的字节数(1023 或剩余/最后一位),稍后针对文件大小进行测试 - 如果等于或更大,则退出循环。

“indexLast”从 0 开始,首先分配 index 的值(第一次通过循环时为 0,之后为 1023 或余数/最后一位),但它从未被引用,因此可以将其注释掉。

"next2Read" 最初分配为 MAXREAD,即 1023。它在这一行中使用:

numberOfBytesRead = bReader.Read( readbuffer, 0, next2Read );

...但此后未引用,因此可以将其删除,并且上面的行更改为:

numberOfBytesRead = bReader.Read( readbuffer, 0, MAXREAD);

"longString" 被初始化为一个空字符串,但是没有在任何地方被引用;但是,由于它是一个全局变量,也许其他地方需要这个值?

"numberOfBytesRead" 被分配了 bReader 的 Read() 方法的返回值。然后将其分配给“index”和“nBytes”。然后在调用 bWriter.Write() 时将其用作“要写入的字节数”。

与“longString”一样,“realTotBytesRead”被分配给此方法,然后在此方法中不被引用,但由于它是一个全局变量,它可以在其他地方使用...

“nBytes”在“numberOfBytesRead”中被赋值,然后用于进度条。似乎可以使用“numberOfBytesRead”并切断中间人,但我猜“nBytes”并没有伤害任何东西(除了让我的头骨不会塌陷的糊状灰色东西)......

“fsize”用于条件分支。它最初设置为 0,然后这样设置:

fsize = (int)Int32.Parse( fFileSz );

“fFileSz”是一个公共静态字符串,它保存文件大小(在别处设置)。

“theN_Stream”是一个网络流。

在调试计算机程序时,您有点像侦探,但不是在黑暗的小巷里追捕坏人并揭露罪犯,而是在吸食行为不端的人。这种侦探工作比另一种更安全——更久坐不动,也更稳重——但是你从备用鞋皮中获得的收益和节省的人寿保险费,你会在突触破裂和过度劳累的脑细胞中损失惨重,WAY超越“云”;在你做/不做的每一件事上总是有一个权衡。

更新 5

我现在预计问题出在其他地方,因为无论文件大小小于、等于还是大于 MAXREAD (1023),此代码似乎都可以工作。伪代码:

//文件大小 < MAXREAD:

if filesize == 1022:
numberOfBytesRead == 1022
index == 1022;
//....breaks out (as it should, it's done), because index == fsize

//文件大小 == MAXREAD: //1023

if filesize == 1023:
numberOfBytesRead == 1023
index == 1023;

//breaks out (as it should, it's done), because index == fsize

//文件大小> MAXREAD:

if filesize == 1024:
numberOfBytesRead == 1023
index == 1023;
...continues to loop again:
numberOfBytesRead == 1
index == 1024;
//breaks out (as it should, it's done), because index == fsize

// 对于任何文件大小 > MAXREAD 都应该相同

更新 6

已找到“神奇数字” - 处理 190KB 大小的文件时应用程序崩溃。显示获取过程的进度条比冻结 - 永远并且在每次文件大小正好如此的情况下;否则很好(如果文件大小小于或大于 190KB,则可以正常工作)。

更新 7

我意识到这是一个糟糕的修复,但遗留代码是如此复杂,[故意?]混淆,和花招——DLL调用exe,反之亦然,多个后台线程触发和停止,闪烁和像来自疯人院的闪光灯一样闪烁——我以这种方式强行临时修复,更改了以下代码:

if( processMessage )
{
                Util.ProcessServerResponse( theMessage.Trim( uDelims.ToCharArray() ) );
}

...对此:

if ( processMessage )
{
                string valToPass = theMessage.Trim(uDelims.ToCharArray());
                if (valToPass.IndexOf("190980") > 0)
                {
                                valToPass = valToPass.Replace("190980", "190978"); 
                }
                Util.ProcessServerResponse( valToPass );
}

// 注意: 1) 出于某种原因,当文件大小为 190980 时,DLL 中会出现无限循环,其中“索引”(已读取的字节数)仍然小于表示要读取的总字节数的值 - 所有其他文件大小或所有其他文件大小的很大一部分,它工作正常...... 2)我不能使用 string.Contains() 来查找“190980”,只是因为它在 .NET 1.1 中不可用

4

0 回答 0